Constant expressions
Several varieties of expressions are known as constant expressions
Preprocessor constant expression
The expression following #if or #elif must expand to
- operators other than assignment, increment, decrement, function-call, or comma whose arguments are preprocessor constant expressions
- integer constants
- character constants
- the special preprocessor operator
defined
Character constants, when evaluated in #if
-expressions, may be interpreted in the source
character set, the execution character set, or some other implementation-defined character set.
Integer arithmetic in |
(since C99) |
Integer constant expression
An integer constant expression is an expression that consists only of
- operators other than assignment, increment, decrement, function-call, or comma, except that cast operators can only cast arithmetic types to integer types
- integer constants
- enumeration constants
- character constants
- floating constants, but only if they are immediately used as operands of casts to integer type
- sizeof operators whose operands are not VLA (since C99)
|
(since C11) |
Integer constant expressions are evaluated at compile time. The following contexts require expressions that are known as integer constant expressions':
- The size of a bit field.
- The value of an enumeration constant
- The
case
label of a switch statement - The size of a non-VLA (since C99) array
- Integer to pointer implicit conversion.
|
(since C99) |
|
(since C11) |
Static initializer
Expressions that are used in the initializers of objects with static and thread_local storage duration must be expressions that may be one of the following
- operators other than assignment, increment, decrement, function-call, or comma, except that cast operators must be converting arithmetic types to other arithmetic types
- integer constants
- floating constants
- enumeration constants
- character constants
- sizeof operators whose operands are not VLA (since C99)
|
(since C11) |
- a null pointer
- lvalue designating an object of static storage duration or a function designator, converted to a pointer either
- by using the unary address-of operator
- by casting an integer constant to a pointer
- by array-to-pointer or function-to-pointer implicit conversion
Unlike with integer constant expressions, static initializer expressions are not required to be evaluated at compile time; the compiler is at liberty to turn such initializers into executable code which is invoked prior to program startup.
static int i = 2 || 1 / 0; // initializes i to value 1
This section is incomplete Reason: other mini-examples |
The value of a floating-point static initializer is never less accurate than the value of the same expression executed at run time, but it may be better.
Floating-point constant expressions
Arithmetic constant expressions of floating-point types that are not used in static initializers are always evaluated as-if during run-time and are affected by the current rounding (if FENV_ACCESS is on) and report errors as specified in math_errhandling.
void f(void) { #pragma STDC FENV_ACCESS ON static float x = 0.0/0.0; // static initializer: does not raise an exception float w[] = { 0.0/0.0 }; // raises an exception float y = 0.0/0.0; // raises an exception double z = 0.0/0.0; // raises an exception }
Notes
If an expression evaluates to a value that is not representable by its type, it cannot be used as a constant expression.
References
- C11 standard (ISO/IEC 9899:2011):
- 6.6 Constant expressions (p: 106-107)
- C99 standard (ISO/IEC 9899:1999):
- 6.6 Constant expressions (p: 95-96)
- C89/C90 standard (ISO/IEC 9899:1990):
- 3.4 CONSTANT EXPRESSIONS