This compiles fine under C99
const int DIM;
int main() {
int tab[DIM];
}
while the following gives the error
int tab[DIM];
int main() {
}
error: variably modified tab at file scope
Why?
I know how to fix it :
#define DIM 10
But this does not provide the answer to my question Thanks for your reply
2 Answers 2
Sizes of variable length arrays are calculated at run-time.
Read for example the following quote from the C 2024 Standard (6.5.4.5 The sizeof and alignof operators):
The
sizeofoperator yields the size (in bytes) of its operand, which can be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
or (6.7.7.3 Array declarators):
If an identifier is declared as having a variably modified type, it shall be an ordinary identifier (as defined in 6.2.3), have no linkage, and have either block scope or function prototype scope. If an identifier is declared to be an object with static or thread storage duration, it shall not have a variable length array type.
Pay attention to that variables declared at file scope have static storage duration.
By the way in the first program you shall initialize the variable DIM because it has the qualifier const and in the second program you missed its definition.:)
In C variables declared with the qualifier const are not constant expressions that are evaluated at compile time.
Thus the first progam is compiled successfully because the declared array has automatic storage duration. Memory for the array is allocated at run time.
The second program is not compiled because the declared at file scope variable length array has static storage duration.
If you will include the directive
#define DIM 10
then the declared array will not be a variable length array because its size is specified with a constant expression that is evaluated at compile time.
4 Comments
Defining an array at the global scope using
const int DIM = 10;
int tab[DIM];
Is not allowed in C (but is supported in c++) because the array dimensions for objects defined at global scope (and local scope with global storage class specified by the static keyword) must be an integer constant expression. Integer constant expressions cannot be computed using the value of const variables as specified in the C Standard (before C23):
6.6 Constant expressions
Constraints
3 Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.
4 Each constant expression shall evaluate to a constant that is in the range of representable values for its type.
8 An integer constant expression shall have integer type and shall only have operands that are integer constants, named and compound literal constants of integer type, character constants,sizeofexpressions whose results are integer constants,alignofexpressions, and floating, named, or compound literal constants of arithmetic type 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 typeof operators, sizeof operator, or alignof operator.
Defining tab as a local array in the main function with automatic storage is allowed since C99 and creates a variable length array (VLA) whose length is computed at run time by evaluating the expression, and is constant for the life time of the object. Note however these limitations:
- the length must not be
0(so the code in the question invokes undefined behavior ifDIMis not initialized). - if the length exceeds available stack space space at the point of definition, undefined behavior is invoked (and probably results in a stack overflow).
- such arrays cannot be initialized with an initializer.
There are other ways to express the array length with an identifier:
#define DIM 10
int tab[DIM];
or
enum { DIM = 10 };
int tab[DIM];
The latest version of the C Standard added the constexpr storage class which allows variables to be used in integer constant expressions. Recent compiler versions (gcc version 13 or clang version 19) with -std=c23, support this version:
constexpr int DIM = 10;
int tab[DIM];
Comments
Explore related questions
See similar questions with these tags.
constexpr int DIM = 10; int tab[DIM];is OK at global scope.