Array of Size Defined by Not Constant Variable

Declaring the array size with a non-constant variable

This is a GCC extension to the standard:

You can use the -pedantic option to cause GCC to issue a warning, or -std=c++98 to make in an error, when you use one of these extensions (in case portability is a concern).

Why is the size of array as a constant variable not allowed in C but allowed in C++?

In C const doesn't mean "constant" (i.e., evaluable at compile time). It merely means read-only.

For example, within a function, this:

const int r = rand();
const time_t now = time(NULL);

is perfectly valid.

The name of an object defined as const int is not a constant expression. That means that (in C prior to C99, and in all versions of C++) it can't be used to define the length of an array.

Although C99 (and, optionally, C11) support variable-length arrays (VLAs), they can't be initialized. In principle, the compiler doesn't know the size of a VLA when it's defined, so it can't check whether an initializer is valid. In your particular case, the compiler quite probably is able to figure it out, but the language rules are designed to cover the more general case.

C++ is nearly the same, but C++ has a special rule that C lacks: if an object is defined as const, and its initialization is a constant expression, then the name of the object it itself a constant expression (at least for integral types).

There's no really good reason that C hasn't adopted this feature. In C, if you want a name constant of an integer type, the usual approach is to use a macro:

 #define LEN 5
...
int arr[LEN] = {1, 2, 3, 4, 5};

Note that if you change the value of LEN, you'll have to re-write the initializer.

Another approach is to use an anonymous enum:

 enum { LEN = 5 };
...
int arr[LEN] = {1, 2, 3, 4, 5};

The name of an enumeration constant is actually a constant expression. In C, for historical reasons, it's always of type int; in C++ it's of the enumeration type. Unfortunately, this trick only works for constants of type int, so it's restricted to values in the range from INT_MIN to INT_MAX.

C++ array with size defined by non-const variable

Standard c++ does not support variable-length arrays, several compilers - notably gcc and clang - do however support them as a carry-over from C (which has supported VLAs since c99). However, Microsoft Visual C++ is not one of those compilers.

How to create an array when the size is a variable not a constant?

int *a = new int[variable_int];

Remember to delete[] the allocated space when you are done with it!

why storage size of 'array' isn't constant

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.

In C, why can't a const variable be used as an array size initializer?

In C, a const-qualified variable is not a constant expression1. A constant expression is something that can be evaluated at compile time - a numeric literal like 10 or 3.14159, a string literal like "Hello", a sizeof expression, or some expression made up of the same like 10 + sizeof "Hello".

For array declarations at file scope (outside the body of any function) or as members of struct or union types, the array dimension must be a constant expression.

For auto arrays (arrays declared within the body of a function that are not static), you can use a variable or expression whose value isn't known until runtime, but only in C99 or later.


  1. C++ is different in this regard - in that language, a const-qualified variable does count as a constant expression.

C++ declare an array based on a non-constant variable?

How can the size of the array come from a non-constant variable?

Currently, because that compiler has a non-standard extension which allows you to use C's variable length arrays in C++ programs.

Does the compiler automatically translate the int array[n] to int* array = new int[n]?

That's an implementation detail. I believe GCC places it on the stack, like normal automatic variables. It may or may not use dynamic allocation if the size is too large for the stack; I don't know myself.

C: Constant length doesn't allow me to declare array

In C opposite to C++ using a constant object in a declaration of an array like this.

const int SIZE = 5;

int grades[SIZE]={78, 80, 75, 82, 83};

declares a variable length array that may not be initialized in its declaration.

Instead you need to use an integral constant expression.

From the C Standard (6.6 Constant expressions).

6 An integer constant expression117) 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.

In this quote the term "integer constants" means integer literals not objects declared with the qualifier const.

You can declare the array for example the following way.

enum { SIZE = 5 };

int grades[SIZE]={78, 80, 75, 82, 83};

//...

Or alternatively you can introduce a macro like.

#define SIZE 5

//...

int grades[SIZE]={78, 80, 75, 82, 83};

//...

Or you could at first declare the array without specifying its size and then introduce the constant that specifiers its size as for example

int grades[]={78, 80, 75, 82, 83};
const size_t SIZE = sizeof( grades ) / sizeof( *grades );

Also these call of printf.

printf("sum is at %p, or %lu and is %lf\n",
ptr_sum, ptr_sum, *ptr_sum);

printf("Grades are at %lu to %lu\n", grades, grades+5);

Are incorrect. You are trying to output a pointer using the conversion specifier lu. You need to use the conversion specifier p.

For example

printf("Grades are at %p to %p\n", ( void * )grades, ( void * )( grades+SIZE ));

Declaring an array with a non-constant size variable

C99 allows variable length arrays to be created on the stack. Your compiler may support this feature. This features is not available in C89.

What the summary told you was true, from a certain point of view. :-)



Related Topics



Leave a reply



Submit