Ashish Yadav
Ashish Yadav

Reputation: 1697

Why can't I create an array with size determined by a global variable?

Why does the array a not get initialized by global variable size?

#include<stdio.h>

int size = 5;

int main()
{
    int a[size] = {1, 2, 3, 4, 5};
    printf("%d", a[0]);

    return 0;
}

The compilation error is shown as

variable-sized object may not be initialized

According to me, the array should get initialized by size.

And what would be the answer if I insist on using global variable (if it is possible)?

Upvotes: 39

Views: 100992

Answers (8)

You cannot create arrays with globally variable size the same reason why you cannot create an array with size determined by a variable in general. The reason is because C++ enables manual memory management, which let's be honest is the reason why we learn this language, and when we allocate memory, we need to keep in mind the advantages and drawbacks of its two types and what we can do with it.

Stack memory literally implements the stack data structure. It has fixed size (a few megabytes as far as I know), and when you put any data on the stack, you push it to the top. Stack fits perfectly for scoped variables that are supposed to only live for a restricted amount of time, which means it will disappear as soon as they see }. Stacks use functions as a unit of grouping all variables, and whenever we call any function (including main), it pushes the total amount of memory this function uses, which is the sum of all variables it allocates. This total size is called stack frame, and it must be constant. Otherwise, if we allocate an array dynamically on the stack:

int size;
scanf("%d", %size);
int array[size];

We don't know how much space we need to reserve for the array and its stack frame responsively, which makes this a forbidden operations. You can, however, initialise it with a constant and constant expression:

constexprt int getSize(int n){
    return n * 2; //This can be anything, I just multiplied to get arbitrary value.
}

const int size = 45;
int constantArray[size]; //Works
int constantExpressionArray[getSize(2)]; //Also works

The reason why constant works is because they are always assured to have the same and known size, and furthermore they don't take up space in memory but compilers just substitute all constant calls with their respective values. Constant expresions also are functions that are executed in the compile-time, which means all values must be known, and then it just substitudes the result (that must always be the same) into its call, which assure the compiler in both cases the size of the arrays are going to be the same (45 for the first one and 4 for the second one).

If you want to have an array with size that veries each time you execute it, you should either allocate it dynamically:

int* dynamicArray = new int[variableSize];

or use std::vector:

std::vector<int> dynamicArray(variableSize);

In the latter case it sets variableSize to be the capacity,which is the length of the array it needs to exceed to resize. If you use it responsibly, you will end up simply using the array underneath it and will only suffer from the performance penalties imposed by dynamically allocating memory and jumping between the functions.

Upvotes: 1

Abderrahmen
Abderrahmen

Reputation: 496

The compiler needs to know the size of the array while declaring it. Because the size of an array doesn't change after its declaration. If you put the size of the array in a variable, you can imagine that the value of that variable will change when the program is executed. In this case, the compiler will be forced to allocate extra memory to this array. In this case, this is not possible because the array is a static data structure allocated on the stack. I hope that this will help.

Upvotes: 4

Steve Jessop
Steve Jessop

Reputation: 279255

In C99, 6.7.8/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.

6.6/2:

A constant expression can be evaluated during translation rather than runtime

6.6/6:

An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts.

6.7.5.2/4:

If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type.

a has variable length array type, because size is not an integer constant expression. Thus, it cannot have an initializer list.

In C90, there are no VLAs, so the code is illegal for that reason.

In C++ there are also no VLAs, but you could make size a const int. That's because in C++ you can use const int variables in ICEs. In C you can't.

Presumably you didn't intend a to have variable length, so what you need is:

#define size 5

If you actually did intend a to have variable length, I suppose you could do something like this:

int a[size];
int initlen = size;
if (initlen > 5) initlen = 5;
memcpy(a, (int[]){1,2,3,4,5}, initlen*sizeof(int));

Or maybe:

int a[size];
for (int i = 0; i < size && i < 5; ++i) {
    a[i] = i+1;
}

It's difficult to say, though, what "should" happen here in the case where size != 5. It doesn't really make sense to specify a fixed-size initial value for a variable-length array.

Upvotes: 34

t0mm13b
t0mm13b

Reputation: 34592

It looks like that your compiler is not C99 Compliant...speaking of which, which compiler are you using? If it's gcc you need to pass the switch '-std=c99'.... if you are using a pre-C99 compiler, that statement is illegal, if that's the case, do this:

int main() { 
   int a[5]={1,2,3,4,5}; 
   printf("%d",a[0]); 
   return 0; 
}

In pre-C99 standard compilers, use a constant instead of a variable.

Edit: You can find out more about the C99 standard here... and here....

Upvotes: 4

IVlad
IVlad

Reputation: 43475

size is a variable, and C does not allow you to declare (edit: C99 allows you to declare them, just not initialize them like you are doing) arrays with variable size like that. If you want to create an array whose size is a variable, use malloc or make the size a constant.

Upvotes: 7

Pratik Deoghare
Pratik Deoghare

Reputation: 37172

#include<stdio.h> 

/* int size=5; */
#define size 5 /* use this instead*/
/*OR*/
int a[size]={1,2,3,4,5};  /* this*/

int main() 
{ 
    int a[size]={1,2,3,4,5}; 
    printf("%d",a[0]); 
    return 0; 
} 

int size means that size is a variable and C does not allow variablesize arrays.

I am using VS2008 where using

const int size=5;  

allows

int a[size]={1,2,3,4,5}; 

Upvotes: 0

indiv
indiv

Reputation: 17856

You don't need to tell the compiler what size the array is if you're giving an initializer. The compiler will figure out the size based on how many elements you're initializing it with.

int a[] = {1,2,3,4,5};

Then you can even let the compiler tell you the size by getting the total size of the array in bytes sizeof(a) and dividing it by the size of one element sizeof(a[0]):

int size = sizeof(a) / sizeof(a[0]);

Upvotes: 10

Seva Alekseyev
Seva Alekseyev

Reputation: 61380

The compiler cannot assume that the value of size is still 5 by the time main() gets control. If you want a true constant in an old-style C project, use:

#define size 5

Upvotes: 9

Related Questions