why "storage size of 'array' isn't constant"

Viewed 953

i am new to C.Last week, I learn to use array to solve problems. I find that when the number of array is too large, like 1024*1024, it will show error. Some people suggest me using static to solve it, but this error(title) makes me more confusing. I think i have defined the arguments, and it should be constant. But it is not. I could not understand.

Summary:

  1. why this error happens?
  2. why a constant is not a constant in C?
  3. how could i solve it without using a ture constant,like 5000?
  4. what function can take the place of static to storage large array?

this is the text code, showing the same error

# include <stdio.h>

int main()
{
    int num = 500;
    static int arr[num] = {0};
    printf("%d",arr[0]);
    return 0;
}
3 Answers

An array with static storage duration, i.e. one defined either at file scope or with the static keyword, must have a size that is a compile time constant. The value of a variable is not a compile time constant which is why you're getting the error.

Declaring the variable in question as const also doesn't qualify because it just means that the variable can't be modified, not that it's a compile time constant.

What you can do is use a preprocessor symbol for a constant. This will get substituted in before the compiler runs.

#define NUM 500

static int arr[NUM] = {0};

why this error happens?

Objects with static storage duration are instantiated (have memory set aside for them) before the program begins execution; that means the size of the arr has to be known at compile time. Even though we have an initializer for num, that's not the same thing as the value num being known at compile time; num doesn't exist until after the program begins execution.

Arrays declared at file scope (outside of any function) or with the static keyword have to be declared with a size that's a constant expression - either an integer constant like 1024, a sizeof expression like sizeof (some-type) or sizeof some-expression, an arithmetic expression involving either of the previous (such as 1024*1024 or 5000 * sizeof (int)), or a macro that expands to any of the above. Or they can be declared without a size and the size is taken from the number of elements in the initializer.

why a constant is not a constant in C?

500 is a constant - num is not. Again, num doesn't exist until run time, but the size of arr has to be known before run time. Adding the const keyword such as

const int num = 500;

doesn't help - all that const does is tell the compiler to yell at you if you try to assign a new value to num. It doesn't make num a constant expression (in C, anyway - in C++ it does).

how could i solve it without using a ture constant,like 5000?

At this point, you're pretty much limited to using dynamic memory.

what function can take the place of static to storage large array?

Use either malloc or calloc to allocate space for the array at runtime:

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
  size_t num = 500; // or whatever value you ultimately need

  /**
   * Dynamically allocate enough space for "num" objects of type "int". 
   * 
   * calloc will zero out the allocated memory (malloc does not).
   *
   * calloc will return NULL if it cannot satisfy the request, so we
   * want to make sure "arr" isn't NULL before trying to use it. 
   * 
   * The type of the *expression* "*arr" is "int", so "sizeof *arr" == "sizeof (int)"
   */
  int *arr = calloc( num, sizeof *arr ); 
                                         
  if ( arr ) 
  {
    printf( "%d\n", arr[0] );

    /**
     * Deallocate "arr" when you're done with it
     */
    free( arr );
  }
  return 0;
}

A big advantage of using dynamic memory like this is that you can resize the array as necessary using realloc - can't do that with fixed-sized arrays (static or not).

As of C99, you can declare arrays with runtime variables as the size:

int num = 500;
int arr[num];

These are called variable length arrays and work just fine (in most C99 and later implementations), but because their size isn't known until runtime they cannot be declared static or at file scope, and they can't be declared with any initializers. Like other auto arrays, they can't be arbitrarily large. And despite their name, they cannot be resized once defined - the "variable" in "variable length" just means their size can be different each time they are instantiated.

static storage duration arrays size has to be the constant expression C17 6.7.6.2/2).

From the C standard:

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.Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof operator.

As you see const integer variables are not listed there and they can't be considered as constant expressions.

examples:

#define SIZE 300

int x = 500;
int a[SIZE];
int b[SIZE+ 'a'];
int c[SIZE + sizeof(x)];

/* and even most modern compilers will accept it*/

int d[SIZE + sizeof(x) + (size_t)sqrt(sizeof(c))];
Related