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
.