Parameter cannot be used as a constant [duplicate] - c++

This question already has answers here:
Declaring Variable length arrays [duplicate]
(3 answers)
Closed 1 year ago.
I have just finished my code, I am stuck on these last two errors:
"the value of parameter "n" cannot be used as a constant." I am using "int n" in my function to calculate average time.
void findavgTime(int option, int pids[], int arrivals[], int n, int bursts[], int quanta) {
int resp[n], ta_time[n], avg_resp_time = 0, avg_ta_time = 0;
How should I go by this?

In C++, the size of an array must be a compile time constant. So you cannot write code like:
int n = 10;
int arr[n]; //incorrect
Correct way to write this would be:
const int n = 10;
int arr[n]; //correct
For the same reason the following code is incorrect in your code as well:
int resp[n], ta_time[n];//incorrect because n must be a compile time constant
You can use std::vector<> for your purpose instead of using built in arrays. So instead of creating arrays you can have/create std::vector named resp and ta_time as follows:
//n denotes the size. You can also use std::vector::reserve for requesting that the vector capacity be at least enough to contain n elements
std::vector<int> resp(n);
std::vector<int> ta_time(n);

Consider replacing your variable-length arrays:
int resp[n], ta_time[n]
with modern C++ std::vector instances:
#include <vector> // for std::vector
std::vector<int> resp(n);
std::vector<int> ta_time(n);
You can still access vector elements using the usual v[i] syntax with a 0-based index, e.g.:
resp[2] = 100; // Access the 3rd element in the vector
VLAs (variable-length arrays) are not part of the C++ standard.
You can only create arrays with compile-time known size, e.g.
constexpr int n = 100; // compile-time constant
int resp[n];

Related

How to dynamically allocate a 2D std::array in C++ or why I should not use it?

I want to malloc an array in my code, and its size should be defined at runtime.
I tried like this:
#include <iostream>
#include <array>
int main(){
int M=4,N=3,P=5;
M=N+P;
std::array<std::array<double,M>,N> arr;
}
But MSVC told me:
a variable with non-static storage duration cannot be used as a non-type argument
I don't find the answer to this in stackoverflow.(The existing question seem not to solve my problem...)
How to dynamically allocate a 2D std::array in C++?
I know I could use std::vector to solve this. But the vector memory size needs to be organized by myself and this would be used many times in my project. And I want to use C++ type code rather than C type...Maybe there is a method to turn a 2D array in C type to std::array, but I can't find it by Google...
So I ask this question...
I mean the M and N should be got dynamically(not changed,but I can only know it in runtime...),like:
#include <iostream>
int main(){
int a=3;
int b=4;
int rowCount=a+b;
int colCout=b-a;
int** a = new int*[rowCount];
for(int i = 0; i < rowCount; ++i)
{
a[i] = new int[colCount];
}
}
I know where is my mistake. I fell into a logical question... If I don't use push_back,the vector works well. If I use it, the array doesn't work, too.
I think the capcity of vector is bigger than its size, I want to avoid this. But another question: How to limit the capacity of std::vector to the number of element show I should use my allocator or std::vector::shrink_to_fit() to avoid it...(There is no guarantee in C++17 if you use reserve(n))
The dynamically allocated array container in C++ is std::vector. std::array is for specifically compile-time fixed-length arrays.
https://cppreference.com is your friend!
But the vector memory size needs to be organized by myself
Not quite sure what you mean with that, but you specify the size of your std::vector using the constructor.
std::vector<std::vector<int>> arr(N);
If you need some special allocator (not just new/malloc), then you can also specify a custom allocator.
Your whole program that you propose is not good C++. A C++ solution would look like:
#include <vector>
int main() {
int a = 3;
int b = 4;
unsigned int rowCount = a + b;
unsigned int colCount = b - a;
std::vector<std::vector<int>> matrix(rowCount);
for (auto& row : matrix) {
row.resize(colCount);
}
}
std::array, like an actual array in C++, requires a constant size. It's what gives it any advantage at all over std::vector.
For a technical explanation as to how that requirement is implemented, remember that template parameters are required to be compile-time constants (since it changes how the code is generated, again at compile-time).
Anyway, you want to use std::vector here. If you know the size you want, give it as a constructor parameter.

set all elements of 2-D array to zero [duplicate]

This question already has answers here:
Fill multidimensional array elements with 0's
(12 answers)
Closed 6 years ago.
int a[100][100]; //globally declared array
int main()
{
while(testcases--)
{
a[100][100]={0};
//rest of code
}
return 0;
}
This code works only for first testcase. For next testcases, it doesn't set the elements to zero.
I can't afford to run a loop to run a loop and iterate all the elements.
I want to perform this task in O(1). Is it possible?
You are using the same array between runs and you want to reset it to zero. You cannot avoid iterating on all the cells and setting them to zero.
Even when initializing to zero on decleration, there's no such thing as promising O(1). The way the compiler initializes is up to the compiler.
First, you seem to have a slight misunderstanding of terms.
This is an initialization:
int a = b;
This is an assignment:
int a;
a = b;
You can initialize an array to zeroes using following code:
int array[10][20] = {0};
Or:
int array[10][20] = {};
Or:
int array[10][20] {};
Keep in mind that global (and static) arrays are zero-initialized by default.
You can fill array with zeroes after it was created like this:
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
array[i][j] = 0;
Or:
for (int (&a)[100] : array) // or for (auto &a : array)
for (int &b : a) // or for (auto &b : a)
b = 0;
Or:
std::memset(array, 0, sizeof array);
P.S.
You can't fill an array with zeroes at runtime for O(1).
Your array is zero-initialized "for the first testcase" simply because it is declared with static storage duration. And such array with static storage duration begins its life zero-initialized.
Your
a[100][100]={0};
line has nothing to with it. This is actually a mere a[100][100] = 0, which is writing a single 0 into a non-existing (out of bounds) element of your array. (The behavior is undefined).
If you wan to reinitialize your array with zeros on each iteration, you have to do it either manually or using a library-level solution, since there is no core-language-level feature that would do it for you. In your case (an array of integers) you can even use the old-fashioned
std::memset(a, 0, sizeof a);
You can also use something clever-but-inefficient like
decltype(a) zeros{};
std::swap(a, zeros);
on each iteration, but it's probably not worth it.

How do I use the for-each loop to scan through an int array object? [duplicate]

This question already has answers here:
Range-based for loop on a dynamic array?
(6 answers)
Closed 6 years ago.
if I create a new int array object using new like below:
int *array = new int[20];
and fill the array with some integers, then attempting to scan through that array with a for-each loop will throw me an error:
for (int x : array) // error
why does this happen and how can I fix it? I tried playing around with the referencer and address notations (* and &) but every combination I tried fails.
ex.
for (int &x : *array) // does not work either.
array is not an array, but a pointer, which can't be used for Range-based for loop, because there's no information about the size of the "array", the begin and end of the "array" can't be deduced.
range_expression - any expression that represents a suitable
sequence (either an array or an object for which begin and end member
functions or free functions are defined, see below) or a
braced-init-list.
You might make it real array, (or use std::array instead of the raw array)
int array[20];
for (int x : array) { processing with x... }
Or write the loop manually:
for (int i = 0; i < 20; i++) { processing with array[i]... }
in for (int x : array), it requires that begin(array) and end(array) are valid. which is not for int*.
it would work for int array[20], std::vector, std::array<int, 20>.

Element count of an array in C++

Let's say I have an array arr. When would the following not give the number of elements of the array: sizeof(arr) / sizeof(arr[0])?
I can thing of only one case: the array contains elements that are of different derived types of the type of the array.
Am I right and are there (I am almost positive there must be) other such cases?
Sorry for the trivial question, I am a Java dev and I am rather new to C++.
Thanks!
Let's say I have an array arr. When
would the following not give the
number of elements of the array:
sizeof(arr) / sizeof(arr[0])?
One thing I've often seen new programmers doing this:
void f(Sample *arr)
{
int count = sizeof(arr)/sizeof(arr[0]); //what would be count? 10?
}
Sample arr[10];
f(arr);
So new programmers think the value of count will be 10. But that's wrong.
Even this is wrong:
void g(Sample arr[]) //even more deceptive form!
{
int count = sizeof(arr)/sizeof(arr[0]); //count would not be 10
}
It's all because once you pass an array to any of these functions, it becomes pointer type, and so sizeof(arr) would give the size of pointer, not array!
EDIT:
The following is an elegant way you can pass an array to a function, without letting it to decay into pointer type:
template<size_t N>
void h(Sample (&arr)[N])
{
size_t count = N; //N is 10, so would be count!
//you can even do this now:
//size_t count = sizeof(arr)/sizeof(arr[0]); it'll return 10!
}
Sample arr[10];
h(arr); //pass : same as before!
Arrays in C++ are very different from those in Java in that they are completely unmanaged. The compiler or run-time have no idea whatsoever what size the array is.
The information is only known at compile-time if the size is defined in the declaration:
char array[256];
In this case, sizeof(array) gives you the proper size.
If you use a pointer as an array however, the "array" will just be a pointer, and sizeof will not give you any information about the actual size of the array.
STL offers a lot of templates that allow you to have arrays, some of them with size information, some of them with variable sizes, and most of them with good accessors and bounds checking.
There are no cases where, given an array arr, that the value of sizeof(arr) / sizeof(arr[0]) is not the count of elements, by the definition of array and sizeof.
In fact, it's even directly mentioned (ยง5.3.3/2):
.... When applied to an array, the result is the total number of bytes in the array. This implies that the size of an array of n elements is n times the size of an element.
Emphasis mine. Divide by the size of an element, sizeof(arr[0]), to obtain n.
Since C++17 you can also use the standardized free function:
std::size(container) which will return the amount of elements in that container.
example:
std::vector<int> vec = { 1, 2, 3, 4, 8 };
std::cout << std::size(vec) << "\n\n"; // 5
int A[] = {40,10,20};
std::cout << std::size(A) << '\n'; // 3
No that would still produce the right value because you must define the array to be either all elements of a single type or pointers to a type. In either case the array size is known at compile time so sizeof(arr) / sizeof(arr[0]) always returns the element count.
Here is an example of how to use this correctly:
int nonDynamicArray[ 4 ];
#define nonDynamicArrayElementCount ( sizeof(nonDynamicArray) / sizeof(nonDynamicArray[ 0 ]) )
I'll go one further here to show when to use this properly. You won't use it very often. It is primarily useful when you want to define an array specifically so you can add elements to it without changing a lot of code later. It is a construct that is primarily useful for maintenance. The canonical example (when I think about it anyway ;-) is building a table of commands for some program that you intend to add more commands to later. In this example to maintain/improve your program all you need to do is add another command to the array and then add the command handler:
char *commands[] = { // <--- note intentional lack of explicit array size
"open",
"close",
"abort",
"crash"
};
#define kCommandsCount ( sizeof(commands) / sizeof(commands[ 0 ]) )
void processCommand( char *command ) {
int i;
for ( i = 0; i < kCommandsCount; ++i ) {
// if command == commands[ i ] do something (be sure to compare full string)
}
}
_countof(my_array) in MSVC
I can thing of only one case: the array contains elements that are of different derived types of the type of the array.
Elements of an array in C++ are objects, not pointers, so you cannot have derived type object as an element.
And like mentioned above, sizeof(my_array) (like _countof() as well) will work just in the scope of array definition.
It seems that if you know the type of elements in the array you can also use that to your advantage with sizeof.
int numList[] = { 0, 1, 2, 3, 4 };
cout << sizeof(numList) / sizeof(int);
// => 5
First off, you can circumvent that problem by using std::vector instead of an array. Second, if you put objects of a derived class into an array of a super class, you will experience slicing, but the good news is, your formula will work. Polymorphic collections in C++ are achieved using pointers. There are three major options here:
normal pointers
a collection of boost::shared_ptr
a Boost.Pointer Container
Let's say I have an array arr. When would the following not give the number of elements of the array: sizeof(arr) / sizeof(arr[0])?
In contexts where arr is not actually the array (but instead a pointer to the initial element). Other answers explain how this happens.
I can thing of only one case: the array contains elements that are of different derived types of the type of the array.
This cannot happen (for, fundamentally, the same reason that Java arrays don't play nicely with generics). The array is statically typed; it reserves "slots" of memory that are sized for a specific type (the base type).
Sorry for the trivial question, I am a Java dev and I am rather new to C++.
C++ arrays are not first-class objects. You can use boost::array to make them behave more like Java arrays, but keep in mind that you will still have value semantics rather than reference semantics, just like with everything else. (In particular, this means that you cannot really declare a variable of type analogous to Foo[] in Java, nor replace an array with another one of a different size; the array size is a part of the type.) Use .size() with this class where you would use .length in Java. (It also supplies iterators that provide the usual interface for C++ iterators.)
Use the Microsoft "_countof(array)" Macro. This link to the Microsoft Developer Network explains it and offers an example that demonstrates the difference between "sizeof(array)" and the "_countof(array)" macro.
Microsoft and the "_countof(array)" Macro
If you can not use C++17, which allows to use std::size(container), you can easily implement your own generic sizeofArray template function as a one-liner:
#include <cstddef>
#include <cstdio>
template< typename T, std::size_t N >
inline constexpr std::size_t sizeofArray( const T(&)[N] ) noexcept { return N; }
int x[10];
void* y[100];
long z[1000];
struct {int x; char y; long z;} s[123];
static_assert( sizeofArray(x) == 10, "error" );
static_assert( sizeofArray(y) == 100, "error" );
static_assert( sizeofArray(z) == 1000, "error" );
static_assert( sizeofArray(s) == 123, "error" );
int main() {
puts( "ok" );
}
test it here: http://cpp.sh/8tio3
It will work if and only if arr is a C-Array (type[size]; except for function parameters!), a reference to a C-Array (type(&)[size]) or a pointer to a C-Array (type(*)[size]).
Note you should use std::size or std::ssize instead with current C++-Standards!
In C++17 you can use std::size:
int arr[] = {1, 2, 3};
auto count = std::size(arr); // type std::size_t, value == 3
In C++20 you can additionally get a signed value by using std::ssize:
int arr[] = {1, 2, 3};
auto count = std::ssize(arr); // type std::ptrdiff_t, value == 3
https://en.cppreference.com/w/cpp/iterator/size
Also note that C++ unfortunately inherited from C that C-Arrays are never passed by value (deep copy) to functions.
void f(int a[3]);
is the same as
void f(int* a);
so you loose the information that a is an array and with this, how much elements it had. The 3 is completely ignored by the compiler!
If you want to preserve the datatype (including the array element count), you can use a pointer or a reference to an C-Array:
void f(int (&a)[3]); // reference to C-Array with 3 elements
void f(int (*a)[3]); // pointer to C-Array with 3 elements
void f(int a[3]); // pointer to int
void f(int* a); // pointer to int
If you want to call functions with Arrays call-by-value, you can use C++-Arrays (std::array) from the C++ standard library:
f(std::array<int, 3> a);
std::array<int, 3> arr = {1, 2, 3};
f(arr); // deep copy
https://en.cppreference.com/w/cpp/container/array
Determine how many numbers are in your array.
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n[10] ;
int l = sizeof(n)/sizeof(n[0]);
cout << l;
return 0;
}
I know is old topic but what about simple solution like while loop?
int function count(array[]) {
int i = 0;
while(array[i] != NULL) {
i++;
}
return i;
}
I know that is slower than sizeof() but this is another example of array count.

Passing array with unknown size to function

Let's say I have a function called MyFunction(int myArray[][]) that does some array manipulations.
If I write the parameter list like that, the compiler will complain that it needs to know the size of the array at compile time. Is there a way to rewrite the parameter list so that I can pass an array with any size to the function?
My array's size is defined by two static const ints in a class, but the compiler won't accept something like MyFunction(int myArray[Board::ROWS][Board::COLS]).
What if I could convert the array to a vector and then pass the vector to MyFunction? Is there a one-line conversion that I can use or do I have to do the conversion manually?
In C++ language, multidimensional array declarations must always include all sizes except possibly the first one. So, what you are trying to do is not possible. You cannot declare a parameter of built-in multidimensional array type without explicitly specifying the sizes.
If you need to pass a run-time sized multidimensional array to a function, you can forget about using built-in multidimensional array type. One possible workaround here is to use a "simulated" multidimensional array (1D array of pointers to other 1D arrays; or a plain 1D array that simulates multidimensional array through index recalculation).
In C++ use std::vector to model arrays unless you have a specific reason for using an array.
Example of a 3x2 vector filled with 0's called "myArray" being initialized:
vector< vector<int> > myArray(3, vector<int>(2,0));
Passing this construct around is trivial, and you don't need to screw around with passing length (because it keeps track):
void myFunction(vector< vector<int> > &myArray) {
for(size_t x = 0;x < myArray.length();++x){
for(size_t y = 0;y < myArray[x].length();++y){
cout << myArray[x][y] << " ";
}
cout << endl;
}
}
Alternatively you can iterate over it with iterators:
void myFunction(vector< vector<int> > &myArray) {
for(vector< vector<int> >::iterator x = myArray.begin();x != myArray.end();++x){
for(vector<int>::iterator y = x->begin();y != x->end();++y){
cout << *y << " ";
}
cout << endl;
}
}
In C++0x you can use the auto keyword to clean up the vector iterator solution:
void myFunction(vector< vector<int> > &myArray) {
for(auto x = myArray.begin();x != myArray.end();++x){
for(auto y = x->begin();y != x->end();++y){
cout << *y << " ";
}
cout << endl;
}
}
And in c++0x for_each becomes viable with lambdas
void myFunction(vector< vector<int> > &myArray) {
for_each(myArray.begin(), myArray.end(), [](const vector<int> &x){
for_each(x->begin(), x->end(), [](int value){
cout << value << " ";
});
cout << endl;
});
}
Or a range based for loop in c++0x:
void myFunction(vector< vector<int> > &myArray) {
for(auto x : myArray){
for(auto y : *x){
cout << *y << " ";
}
cout << endl;
}
}
*I am not near a compiler right now and have not tested these, please feel free to correct my examples.
If you know the size of the array at compile time you can do the following (assuming the size is [x][10]):
MyFunction(int myArray[][10])
If you need to pass in a variable length array (dynamically allocated or possibly just a function which needs to take different sizes of arrays) then you need to deal with pointers.
And as the comments to this answer state:
boost::multiarray may be appropriate since it more efficiently models a multidimensional array. A vector of vectors can have performance implications in critical path code, but in typical cases you will probably not notice an issue.
Pass it as a pointer, and take the dimension(s) as an argument.
void foo(int *array, int width, int height) {
// initialize xPos and yPos
assert(xPos >= 0 && xPos < width);
assert(yPos >= 0 && yPos < height);
int value = array[yPos * width + xPos];
}
This is assuming you have a simple two-dimensional array, like int x[50][50].
There are already a set of answers with the most of the common suggestions: using std::vector, implementing a matrix class, providing the size of the array in the function argument... I am only going to add yet another solution based on native arrays --note that if possible you should use a higher level abstraction.
At any rate:
template <std::size_t rows, std::size_t cols>
void function( int (&array)[rows][cols] )
{
// ...
}
This solution uses a reference to the array (note the & and the set of parenthesis around array) instead of using the pass-by-value syntax. This forces the compiler not to decay the array into a pointer. Then the two sizes (which could have been provided as compile time constants can be defined as template arguments and the compiler will deduct the sizes for you.
NOTE: You mention in the question that the sizes are actually static constants you should be able to use them in the function signature if you provide the value in the class declaration:
struct test {
static const int rows = 25;
static const int cols = 80;
};
void function( int *array[80], int rows ) {
// ...
}
Notice that in the signature I prefer to change the double dimension array for a pointer to an array. The reason is that this is what the compiler interprets either way, and this way it is clear that there is no guarantee that the caller of the function will pass an array of exactly 25 lines (the compiler will not enforce it), and it is thus apparent the need for the second integer argument where the caller passes the number of rows.
You can't pass an arbitrary size like that; the compiler doesn't know how to generate the pointer arithmetic. You could do something like:
MyFunction(int myArray[][N])
or you could do:
MyFunction(int *p, int M, int N)
but you'll have to take the address of the first element when you call it (i.e. MyFunction(&arr[0][0], M, N).
You can get round all of these problems in C++ by using a container class; std::vector would be a good place to start.
The compiler is complaining because it needs to know the size of the all but the first dimension to be able to address an element in the array. For instance, in the following code:
int array[M][N];
// ...
array[i][j] = 0;
To address the element, the compiler generates something like the following:
*(array+(i*N+j)) = 0;
Therefore, you need to re-write your signature like this:
MyFunction(int array[][N])
in which case you will be stuck with a fixed dimension, or go with a more general solution such as a (custom) dynamic 2D array class or a vector<vector<int> >.
Use a vector<vector<int> > (this would be cheating if underlying storage was not guaranteed to be contiguous).
Use a pointer to element-of-array (int*) and a size (M*N) parameter. Here be dragons.
First, lets see why compiler is complaining.
If an array is defined as int arr[ ROWS ][ COLS ]; then any array notation arr[ i ][ j ] can be translated to pointer notation as
*( arr + i * COLS + j )
Observe that the expression requires only COLS, it does not require ROWS. So, the array definition can be written equivalently as
int arr [][ COLS ];
But, missing the second dimension is not acceptable. For little more details, read here.
Now, on your question:
Is there a way to rewrite the
parameter list so that I can pass an
array with any size to the function?
Yes, perhaps you can use a pointer, e.g. MyFunction( int * arr );. But, think about it, how would MyFunction() know where to stop accessing the array? To solve that you would need another parameter for the length of the array, e.g. MyFunction( int * arr, size_t arrSize );
Yes: MyFunction(int **myArray);
Careful, though. You'd better know what you're doing. This will only accept an array of int pointers.
Since you're trying to pass an array of arrays, you'll need a constant expression as one of the dimentions:
MyFunction(int myArray[][COLS]);
You'll need to have COLS at compile time.
I suggest using a vector instead.
Pass a pointer and do the indexing yourself or use a Matrix class instead.
yes - just pass it as pointer(s):
MyFunction(int** someArray)
The downside is that you'll probably need to pas the array's lengths as well
Use MyFunction(int *myArray[])
If you use MyFunction(int **myArray) an pass int someArray[X][Y], the program will crash.
EDIT: Don't use the first line, it's explained in comments.
I don't know about C++, but the C99 standard introduced variable length arrays.
So this would work in a compiler that supports C99:
void func(int rows, int cols, double[rows][cols] matrix) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
printf("%f", matrix[r][c]);
}
}
}
Note that the size arguments come before the array. Really, only the number of columns has to be known at compile time, so this would be valid as well:
void func(int rows, int cols, double[][cols] matrix)
For three or more dimensions, all but the first dimension must have known sizes. The answer ArunSaha linked to explains why.
Honestly, I don't know whether C++ supports variable-length arrays, so this may or may not work. In either case, you may also consider encapsulating your array in some sort of matrix class.
EDIT: From your edit, it looks like C++ may not support this feature. A matrix class is probably the way to go. (Or std::vector if you don't mind that the memory may not be allocated contiguously.)
Don't pass an array, which is an implementation detail. Pass the Board
MyFunction(Board theBoard)
{
...
}
in reality my array's size is defined by two static const ints in a class, but the compiler won't accept something like MyFunction(int myArray[Board::ROWS][Board::COLS]).
That's strange, it works perfectly fine for me:
struct Board
{
static const int ROWS = 6;
static const int COLS = 7;
};
void MyFunction(int myArray[Board::ROWS][Board::COLS])
{
}
Maybe ROWS and COLS are private? Can you show us some code?
In C++, using the inbuilt array types is instant fail. You could use a boost::/std:: array of arrays or vector of arrays. Primitive arrays are not up to any sort of real use
In C++0x, you can use std::initializer_list<...> to accomplish this:
MyFunction(std::initializer_list<std::initializer_list<int>> myArray);
and use it (I presume) like this (with the range based for syntax):
for (const std::initializer_list<int> &subArray: myArray)
{
for (int value: subArray)
{
// fun with value!
}
}