Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is int x[n] wrong where n is a const value?

I cannot understand why doing this is wrong:

const int n = 5;  int x[n] = { 1,1,3,4,5 }; 

even though n is already a const value.

While doing this seems to be right for the GNU compiler:

const int n = 5; int x[n]; /*without initialization*/ 

I'm aware of VLA feature of C99 and I think it's related to what's going on but I just need some clarification of what's happening in the background.

like image 883
Yahia Farghaly Avatar asked Feb 02 '16 19:02

Yahia Farghaly


People also ask

Does it matter where you put const?

To start you probably know that const can be used to make either an object's data or a pointer not modifiable or both. However you can also use the syntax: Object const *obj; // same as const Object* obj; The only thing that seems to matter is which side of the asterisk you put the const keyword.

How does the value of a const change?

Changing Value of a const variable through pointerBy assigning the address of the variable to a non-constant pointer, We are casting a constant variable to a non-constant pointer. The compiler will give warning while typecasting and will discard the const qualifier.

Why should you not use #define to declare a constant?

The disadvantage of #define is that is replaces every occurence of the name, while const variables get normal lookup, so you have less risk of naming conflicts and it's not typesafe. The advantage of #define is that it guarantees constness and therefore there will be no backing variable.

Can const int value be changed?

The constant variable values cannot be changed after its initialization.


1 Answers

The key thing to remember is that const and "constant" mean two quite different things.

The const keyword really means "read-only". A constant is a numeric literal, such as 42 or 1.5 (or an enumeration or character constant). A constant expression is a particular kind of expression that can be evaluated at compile time, such as 2 + 2.

So given a declaration:

const int n = 5; 

the expression n refers to the value of the object, and it's not treated as a constant expression. A typical compiler will optimize a reference to n, replacing it by the same code it would use for a literal 5, but that's not required -- and the rules for whether an expression is constant are determined by the language, not by the cleverness of the current compiler.

An example of the difference between const (read-only) and constant (evaluated at compile time) is:

const size_t now = time(NULL); 

The const keyword means you're not allowed to modify the value of now after its initialization, but the value of time(NULL) clearly cannot be computed until run time.

So this:

const int n = 5; int x[n]; 

is no more valid in C than it would be without the const keyword.

The language could (and IMHO probably should) evaluate n as a constant expression; it just isn't defined that way. (C++ does have such a rule; see the C++ standard or a decent reference for the gory details.)

If you want a named constant with the value 5, the most common way is to define a macro:

#define N 5 int x[N]; 

Another approach is to define an enumeration constant:

enum { n = 5 }; int x[n]; 

Enumeration constants are constant expressions, and are always of type int (which means this method won't work for types other than int). And it's arguably an abuse of the enum mechanism.

Starting with the 1999 standard, an array can be defined with a non-constant size; this is a VLA, or variable-length array. Such arrays are permitted only at block scope, and may not have initializers (since the compiler is unable to check that the initializer has the correct number of elements).

But given your original code:

const int n = 5;  int x[n] = { 1,1,3,4,5 }; 

you can let the compiler infer the length from the initializer:

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

And you can then compute the length from the array's size:

const int x_len = sizeof x / sizeof x[0]; 
like image 151
Keith Thompson Avatar answered Oct 14 '22 15:10

Keith Thompson