Why Is the Size of Array as a Constant Variable Not Allowed in C But Allowed in C++

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: 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 ));

Array size with const variable in C

Variable Length Arrays may have only automatic storage duration. VLAs were introduced in C99.

It is not allowed to declare a VLA with the static storage duration because the size of VLA is determinated at the run time (see below)

Before this Standard you can use either a macro like

#define SIZE 10

//...

int a[SIZE];

or a enumerator of an enumeration like

enum { SIZE = 10; }

//...

int a[SIZE];

By the way you may remove the const qualifier and just write

int size = 10;

instead of

const int size = 10;

(In C++ you have to use the const qualifier though in C++ there are no VLAs except that some compilers can have their own language extensions)

Take into account that the sizeof operator for VLAs is calculated at the run-time instead of the compile-time.

Why we cannot create an array with a constant in c

In C:

20 is a constant.

unsigned int const size_of_list is not a constant.

Title: "Why we cannot create an array with a constant in c" does not apply to this code.

const char* list_of_words[size_of_list] = {"Some", "Array"}; // Bad

An issue here (and the error message) is why a VLA cannot be initialized. That is answered here.

With a constant, array initialization works fine.

const char* list_of_words[20] = {"Some", "Array"};  // Good

Another issue is mistaking that const makes an object a constant. It does not.


Alternative C code

int main(){
// unsigned int const size_of_list = 20;
#define size_of_list 20u

const char* list_of_words[size_of_list] = {"Some", "Array"};
for (unsigned int writing_index = 0; writing_index < size_of_list; writing_index ++)
;
return 0;
}

If you can specify the size in the array itself, then you can get it's size with the sizeof operator. This may be better suited for having the compiler count up the size instead manual counting. When not using C99 VLAs, sizeof also yields a compile-time constant.

#include <stddef.h> /* size_t */
int main(void) {
const char* list_of_words[] = {"Some", "Array"};
const char list_of_char[sizeof list_of_words
/ sizeof *list_of_words] = {'S','A'};
const size_t size_of_list
= sizeof list_of_words / sizeof *list_of_words;
for (size_t writing_index = 0;
writing_index < size_of_list; writing_index ++);
return 0;
}

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.

Why are those definitions not legal in C?

suppose you have

int a = 42;
const int *b = &a;

now *b is const ie read-only. You are not allowed to change *b without casting the const away (thanks Eric Postpischil)

// *b = -1; // not allowed
a = -1;
printf("%d\n", *b); // print -1

The point is: the value of a const qualified object may change. A constant value never changes.

Why am I being allowed to use a const qualified variable as an array size in C?

c99 support variable length arrays but c90 does not support variable length arrays, you can see this more clearly if you are using gcc and try to compile with these arguments:

gcc -std=c89 -pedantic

this will give you the following warning:

warning: ISO C90 forbids variable length array ‘y’ [-Wvla]

but if you compile using c99 it is perfectly fine:

gcc -std=c99 -pedantic 

As pointed out by John Bode as of the 2011 C standard variable length arrays(VLA) are now optional. Here is a Dr Dobbs article on VLA and also a link to the gcc docs as pointed out by Wayne Conrad.

is defining size of arrays as a variable enter by user legal?

Variable-length arrays (VLAs) are legal from C99 onwards, although some compilers like GCC will allow them as an extension in older versions too. From C11 onwards, compilers are no longer required to support VLAs and will define __STDC_NO_VLA__ as 1 if they don't support it.

VLAs are inherently risky: either you know the maximum size of your data beforehand, in which case you can allocate a fixed-length array, or you don't, in which case you run the risk of overflowing the stack.

It's worth noting that in C++, variable-length arrays were never part of the standard.



Related Topics



Leave a reply



Submit