I was writing the following code
#include<stdio.h>
void fun(int n) {
int a[n] = {0};
}
void main() {
int a[4] = {0};
int i = 0;
fun(3);
}
and got this error
test.c: In function 'fun':
test.c:5:5: error: variable-sized object may not be initialized
while if I change the function fun to:-
void fun(int n) {
int a[n], i = 0;
for(i = 0; i < n; i++) {
a[i] = 0;
}
}
it works fine.
I know that the error is occuring because it's not allowed in the compiler's specification but what i want to know is why is it not possible to be implemented?
Is it due to some compile time or run time evaluation issue?
I have seen the answer of other question but i need a more elaborated answer.
Variable Length Array cannot be initialized like this
int a[n]={0};
From C Standards#6.7.9p3 Initialization [emphasis added]
The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.
Using loop is one way to initialize the variable length array's. You can also use memset like this:
memset(a, 0, sizeof a);
Additional:
The C99 compiler should support the Variable Length Array's but they were made optional in C11 compiler.
An easy way is to send the size of array along with other parameters
Remember that you should send size before an array with that size
void fun(int n,int a[n]){
}
Although you have other alternatives like sizeof()
As an addition to H.S. answer:
From C Standards#6.7.9p3 Initialization [emphasis added]
The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.
This is probably because Initializers have to be constant expressions. Constant expression have a definite value at compile time.
A {0} is an incomplete Initializer and the compiler would fill up the remaining values with 0.
If you have a VLA the compiler does not know the length of the Array and thus can not generate the initializer for it.
This depends on your compiler actually.
In old C You couldn't have variable size arrays. In function fun you use a as an array with variable size n. This is not allowed in old C. However, C99 and C11 standards support variable size arrays, so perhaps you have an old compiler. (DevC?) If you want to use some type of variable arrays in older C compilers, you have to use malloc and free.
Perhaps you wanted to write this code in C++? C++ doesn't support variable size arrays also, but the gcc compiler can run this code.
Check this out:
Why aren't variable-length arrays part of the C++ standard?
If you are using DevC, I think that if you change your file from test.c to test.cpp this code will work.
Related
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
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
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.
int array[5][3];
(obviously) creates a multi-dimensional C array of 5 by 3. However,
int x = 5;
int array[x][3];
does not. I've always thought it would. What don't I understand about C arrays? If they only allow a constant to define the length of a C array, is there a way to get around this in some way?
In ANSI C (aka C89), all array dimensions must be compile-time integer constants (this excludes variables declared as const). The one exception is that the first array dimension can be written as an empty set of brackets in certain contexts, such as function parameters, extern declarations, and initializations. For example:
// The first parameter is a pointer to an array of char with 5 columns and an
// unknown number of rows. It's equivalent to 'char (*array_param)[5]', i.e.
// "pointer to array 5 of char" (this only applies to function parameters).
void some_function(char array_param[][5])
{
array_param[2][3] = 'c'; // Accesses the (2*5 + 3)rd element
}
// Declare a global 2D array with 5 columns and an unknown number of rows
extern char global_array[][5];
// Declare a 3x2 array. The first dimension is determined by the number of
// initializer elements
int my_array[][2] = {{1, 2}, {3, 4}, {5, 6}};
C99 added a new feature called variable-length arrays (VLAs), where the first dimension is allowed to be a non-constant, but only for arrays declared on the stack (i.e. those with automatic storage). Global arrays (i.e. those with static storage) cannot be VLAs. For example:
void some_function(int x)
{
// Declare VLA on the stack with x rows and 5 columns. If the allocation
// fails because there's not enough stack space, the behavior is undefined.
// You'll probably crash with a segmentation fault/access violation, but
// when and where could be unpredictable.
int my_vla[x][5];
}
Note that the latest edition of the C standard, C11, makes VLAs optional. Objective-C is based off of C99 and supports VLAs. C++ does not have VLAs, although many C/C++ compilers such as g++ which support VLAs in their C implementation also support VLAs in C++ as an extension.
int x = 5;
int array[x][3];
Yes, it does. It's a C99 variable length array. Be sure to switch to C99 mode and be sure to have array declared at block or function scope. Variable length arrays cannot be declared at file scope.
Try:
const int x=5;
int array[x][3];
As you said x has to be a constant or else think what would happen if in the middle of the program you changed the value of x,what would be the dimension of array:(
But by declaring it constan if you change the value of x you get a compile error.
why can we do this in c?
int n;
scanf("%d",&n);
int a[n];
I thought array is located memory during load time but seems like the above example works during runtime.
Do I misunderstand any thing? can you guys help?
Thanks,
I am no expert in C, but this could be a variable-length array as added by C99 and supported by GCC, for example. GCC allocates the memory for such array on stack, so that it gets automatically freed when you return from the function.
Variable-length arrays are not found in C89, but are a new feature in C99.
I thought array is *al*located memory during load time but seems like the above example works during run-time.
Yes, ordinary arrays like <datatype> <Array_Name> [<size>] is allocated memory during load time it is there in C89 and also existed in C99.
But in the code snippet int a[n]; is a Variable Length Array or VLA for short.VLA's in C99 are defined just like any other array, except that the length doesn’t need to be a compile-time constant.
A decent article on the need of VLAs can be found here :http://www.ddj.com/cpp/184401444 :)
Given how your code is written (specifically, that you have a statement), this must be code within a function.
While I'm not sure if this is strictly required in the spec, within a function, all auto (i.e. function level, not static) arrays are put on the stack. So regardless of whether you have a regular or VL array, the memory is allocated at runtime.
The memory for non-auto arrays is not handled at runtime so do no support VLA. If you try to compile the following code:
extern int size;
char buff1[size];
void doit(int x)
{
static int buff2[x];
int buff3[x];
}
On the compiler I tested this on (gcc 4.2.1), I got following errors:
moo.c:2: error: variably modified ‘buff1’ at file scope
moo.c: In function ‘doit’:
moo.c:6: error: storage size of ‘buff2’ isn’t constant