Are arrays with a defined const allowed in C++? - arrays

I tried to run the following code with a C++ compiler:
#include <iostream>
#include <string>
using namespace std;
int MAX=10;
int list[MAX];
int main()
{
int sum =0;
for (int i = 0; i<=MAX; ++i){
list[i]=i;
}
for (int i = 0; i<=MAX; ++i){
sum=sum+list[i];
}
cout << sum << endl;
}
But received this error:
"integer array bound is not an integer constant before ‘]’ token"
I don't understand why this is an error because I have defined MAX as 10 right before
int list[MAX]
so shouldn't it work?
Appreciate any help

No compiler error message here, just exactly what the error message says. You haven't included a const before your int MAX declaration.
Capital letters and never changing the value of MAX doesn't mean it's a constant.
Note that some compilers accept having a variable (i.e. int MAX = 10; instead of const int MAX = 10; for array initialization. Don't rely on this because it shouldn't occur.
If you want to use a variable to initialize an array, you need to use pointers:
int size;
cin >> size;
int *list = new int[size];

I don't understand why this is an error because I have defined MAX as 10 right before int list[MAX]
You defined MAX as 10 but you didn't define MAX as constant. It's an error because the compiler insists that (in this case) the array bound must be an integer constant.
One way to fix the error is to make MAX constant...
const int MAX = 10;
int list[MAX];
Another way to avoid the error is to move the array off the stack and onto the heap (since the bound of a heap array doesn't have to be constant) …
auto list = new int[MAX];
… however this changes the type of list from int[10] to int * and also forces you to become responsible for managing the life of list by calling delete when appropriate (which can be a non-trivial challenge) …
delete [] list;
Not deleting list correctly can cause memory leaks.
You can avoid the error and avoid responsibility for managing the array by using a unique_ptr …
std::unique_ptr<int[]> list{ new int[MAX] };
However many well regarded authorities would argue that using a container like std::vector or std::array would be a better approach. For example, in Effective Modern C++ Scott Meyers says this...
The existence of std::unique_ptr for arrays should be of only intellectual interest to you, because std::array, std::vector, and std::string are virtually always better data structure choices than raw arrays. About the only situation I can conceive of when a std::unique_ptr would make sense would be when you’re using a C-like API that returns a raw pointer to a heap array that you assume ownership of.
At this point you may be wondering why MAX has to be constant in your original code. I'm not a language lawyer but I believe the short answer is because the C++ Standard says it must be so.
For insight into why the standard imposes that requirement you could read some of the answers to the question Why aren't variable-length arrays part of the C++ standard?

Related

C incomplete declarations

I am looking for an explanation to the following statement regarding array declarators in this book.
The concept of composite types (§6.1.2.6) was introduced to provide
for the accretion of information from incomplete declarations, such as
array declarations with missing size, and function declarations with
missing prototype (argument declarations). Type declarators
are therefore said to specify compatible types if they agree
except for the fact that one provides less information of this sort
than the other.
The declaration of 0-length arrays is invalid, under the general
principle of not providing for 0-length objects. The only common use
of this construct has been in the declaration of dynamically allocated
variable-size arrays, such as
struct segment {
short int count;
char c[N];
};
struct segment * new_segment( const int length ) {
struct segment * result;
result = malloc( sizeof segment + (length-N) );
result->count = length;
return result;
}
In such usage, N would be 0 and (length-N) would be written as length.
But this paradigm works just as well, as written, if N is 1.
Specifically I am interested in what is the motivation of this paragraph and to understand that code snippet. Where does the N come from in the new_segment function?
Where does the N come from in the new_segment function?
It is simply a placeholder in the text rather than intended to be an actual N in real code. As we see from this sentence:
In such usage, N would be 0 and (length-N) would be written as length. But this paradigm works just as well, as written, if N is 1.
the text wishes to discuss two declarations of the c member, one with:
struct segment {
short int count;
char c[0];
};
and the other with:
struct segment {
short int count;
char c[1];
};
Writing them out requires more space, and also the following sample code for the new_segment function must be repeated. Further, it might be a bit less clear how the value of N changed new_segment if it were written as two separate instances with different literal constants rather than with N showing where the change occurs (although the affect is minor in any case).
The text is saying it is fairly easy for a programmer to use either 0 or 1 as the array size; it merely requires a minor adjustment when allocating space.

C 2 errors: subscripted value is neither array nor pointer nor vector and in function createPoint variable-sized object may not be initialized [duplicate]

Why do I receive the error "Variable-sized object may not be initialized" with the following code?
int boardAux[length][length] = {{0}};
I am assuming that you are using a C99 compiler (with support for dynamically sized arrays). The problem in your code is that at the time when the compilers sees your variable declaration it cannot know how many elements there are in the array (I am also assuming here, from the compiler error that length is not a compile time constant).
You must manually initialize that array:
int boardAux[length][length];
memset( boardAux, 0, length*length*sizeof(int) );
You receive this error because in C language you are not allowed to use initializers with variable length arrays. The error message you are getting basically says it all.
6.7.8 Initialization
...
3 The type of the entity to be initialized shall be
an array of unknown size or an object
type that is not a variable length
array type.
This gives error:
int len;
scanf("%d",&len);
char str[len]="";
This also gives error:
int len=5;
char str[len]="";
But this works fine:
int len=5;
char str[len]; //so the problem lies with assignment not declaration
You need to put value in the following way:
str[0]='a';
str[1]='b'; //like that; and not like str="ab";
After declaring the array
int boardAux[length][length];
the simplest way to assign the initial values as zero is using for loop, even if it may be a bit lengthy
int i, j;
for (i = 0; i<length; i++)
{
for (j = 0; j<length; j++)
boardAux[i][j] = 0;
}
Variable length arrays are arrays whose length is not known by the compiler at compile time. In your case length is a variable. I conclude this, because if length was a e.g. preprocessor macro defined as a literal integer your initialization would work. The first C language standard from 1989 did not allow variable length arrays, they were added in 1999. Still the C standard does not allow these to be initialized with an expression like yours (although one could argue that it could or should allow it).
The best way to initialize a variable array is like this:
int boardAux[length][length];
memset( boardAux, 0, sizeof(boardAux) );
memset is a very fast standard library function for initializing memory (to 0 in the above case). sizeof(boardAux) returns the number of bytes occupied by boardAux. sizeof is always available but memset requires #include <string.h>. And yes - sizeof allows a variable sized object as argument.
Note that if you have a normal array (not variable length) and just want to initialize the memory to zero you never need nested brackets, you can initialize it simply like this:
struct whatEver name[13][25] = {0};
The array is not initialized with the memory specified anf throws an error
variable sized array may not be initialised
I prefer usual way of initialization,
for (i = 0; i < bins; i++)
arr[i] = 0;
The question is already answered but I wanted to point out another solution which is fast and works if length is not meant to be changed at run-time. Use macro #define before main() to define length and in main() your initialization will work:
#define length 10
int main()
{
int boardAux[length][length] = {{0}};
}
Macros are run before the actual compilation and length will be a compile-time constant (as referred by David Rodríguez in his answer). It will actually substitute length with 10 before compilation.
int size=5;
int ar[size ]={O};
/* This operation gives an error -
variable sized array may not be
initialised. Then just try this.
*/
int size=5,i;
int ar[size];
for(i=0;i<size;i++)
{
ar[i]=0;
}
Simply declare length to be a cons, if it is not then you should be allocating memory dynamically

error: variable-sized object may not be initialized in c compiler [duplicate]

Why do I receive the error "Variable-sized object may not be initialized" with the following code?
int boardAux[length][length] = {{0}};
I am assuming that you are using a C99 compiler (with support for dynamically sized arrays). The problem in your code is that at the time when the compilers sees your variable declaration it cannot know how many elements there are in the array (I am also assuming here, from the compiler error that length is not a compile time constant).
You must manually initialize that array:
int boardAux[length][length];
memset( boardAux, 0, length*length*sizeof(int) );
You receive this error because in C language you are not allowed to use initializers with variable length arrays. The error message you are getting basically says it all.
6.7.8 Initialization
...
3 The type of the entity to be initialized shall be
an array of unknown size or an object
type that is not a variable length
array type.
This gives error:
int len;
scanf("%d",&len);
char str[len]="";
This also gives error:
int len=5;
char str[len]="";
But this works fine:
int len=5;
char str[len]; //so the problem lies with assignment not declaration
You need to put value in the following way:
str[0]='a';
str[1]='b'; //like that; and not like str="ab";
After declaring the array
int boardAux[length][length];
the simplest way to assign the initial values as zero is using for loop, even if it may be a bit lengthy
int i, j;
for (i = 0; i<length; i++)
{
for (j = 0; j<length; j++)
boardAux[i][j] = 0;
}
Variable length arrays are arrays whose length is not known by the compiler at compile time. In your case length is a variable. I conclude this, because if length was a e.g. preprocessor macro defined as a literal integer your initialization would work. The first C language standard from 1989 did not allow variable length arrays, they were added in 1999. Still the C standard does not allow these to be initialized with an expression like yours (although one could argue that it could or should allow it).
The best way to initialize a variable array is like this:
int boardAux[length][length];
memset( boardAux, 0, sizeof(boardAux) );
memset is a very fast standard library function for initializing memory (to 0 in the above case). sizeof(boardAux) returns the number of bytes occupied by boardAux. sizeof is always available but memset requires #include <string.h>. And yes - sizeof allows a variable sized object as argument.
Note that if you have a normal array (not variable length) and just want to initialize the memory to zero you never need nested brackets, you can initialize it simply like this:
struct whatEver name[13][25] = {0};
The array is not initialized with the memory specified anf throws an error
variable sized array may not be initialised
I prefer usual way of initialization,
for (i = 0; i < bins; i++)
arr[i] = 0;
The question is already answered but I wanted to point out another solution which is fast and works if length is not meant to be changed at run-time. Use macro #define before main() to define length and in main() your initialization will work:
#define length 10
int main()
{
int boardAux[length][length] = {{0}};
}
Macros are run before the actual compilation and length will be a compile-time constant (as referred by David Rodríguez in his answer). It will actually substitute length with 10 before compilation.
int size=5;
int ar[size ]={O};
/* This operation gives an error -
variable sized array may not be
initialised. Then just try this.
*/
int size=5,i;
int ar[size];
for(i=0;i<size;i++)
{
ar[i]=0;
}
Simply declare length to be a cons, if it is not then you should be allocating memory dynamically

Arduino IDE: array bound

I get an array bound error in Arduino IDE for the following code. This can be solved if I put the outcome of the calculation for the "sample" (which is 50 in this case) but this is kind of dummy solution. I want the software to do it for myself not me doing hand calculations and insert it. What would be the workaround? Thanks!
int des_freq=200;
int ncycles=5;
int sample =1000/(des_freq*T);
float V_sin_bip[sample]; // error here
As of version 1.6.6, Arduino IDE enables C++11 by default. But C++ standard (till C++11) doesn’t support variable-sized arrays. The C++11 standard mentions array size as a constant-expression.
float V_sin_bip[sample]; uses variable expression to mention array size. Thus, an error occurs.
If you want a "variable-length array" (better called a "dynamically sized array" in C++, since proper variable-length arrays aren't allowed), you either have to dynamically allocate memory yourself:
int n = 10;
double* a = new double[n]; // Don't forget to delete [] a; when you're done!
Or, better yet, use a standard container:
int n = 10;
std::vector<double> a(n); // Don't forget to #include <vector>
If you still want a proper array, you can use a constant, not a variable, when creating it:
const int n = 10;
double a[n]; // now valid, since n isn't a variable (it's a compile time constant)

initialize the array with pointers to ints

Hey I'm working on a problem and here is what I have to do:-
Write a function called initarray that takes an array of pointers to int and an int representing the size of the array, as arguments. The function should initialize the array with pointers to ints (use malloc) that have a value corresponding to the array indices at which a pointer to them are stored (the pointer stored at array index 2 should point to an integer with a value of 2).
So far I've written this, but It's giving me an error "[Error] variable-sized object may not be initialized"
Can you tell me what I'm doing wrong here?
#include<stdio.h>
void initArray(int **a, int sz){
int i;
for (i = 0; i < sz; i++) {
a[i] = calloc (1, sizeof **a);
*a[i] = i;
}
}
int main(){
const int Var = 10;
int *array[Var] = {NULL};
initArray(array,3);
}
For historical reasons, the value of a const variable is never considered a constant expression in C.
So if you use it as an array dimension, then the array is a variable-length array, and variable-length arrays are not allowed to have initializers.
One solution not mentioned yet is to use enum. Enumerators are in fact constant expressions, and they don't suffer from the same "bigger hammer" issue as preprocessor macros:
int main()
{
enum { Var = 10 };
int *array[Var] = {NULL};
initArray(array,3);
}
C has no symbolic constants with user-defined type. You encountered one of the differences to C++.
The const qualifier just is a guarantee you give to the compiler you will not change the variable(!) Var.
Arrays with initialiser and global arrays require a constant expressing which can be evaluated at compile-time. As Var is semantically still a variable, you cannot use it.
The C-way to emulate symbolic constants are macros:
#define ARRAY_SIZE 10
...
// in your function:
int *array[ARRAY_SIZE] = ...
Macros are handled by the preprocessor and are a textual replacement before the actual compiler sees the code.
Note I changed the name to a more self-explanatory one. The macro should also be at the file-level, typically near the beginning to allow easier modifications. Using the integer constant 10 directly in the code is a bad idea. Such magic numbers are often cause of errors when a modification is required.
The error would suggest that you can't use an initializer (the = {NULL} in your main function) on a variable-sized object. While it looks like it isn't variable (because of the const on Var, and because 10 is a constant) it sees it as variable because you're accessing it through a variable. If you use:
int *array[10] = {NULL}
I think your snippet will work fine.

Resources