Search code examples
clanguage-lawyerundefined-behaviorc99

Meaning and example of Undefined behaviours related to constant expression in C99


I don't understand the Undefined Behaviours in C99 related to constant expression.

For example:

An expression that is required to be an integer constant expression does not have an integer type; has operands that are not integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, or immediately-cast floating constants; or contains casts (outside operands to sizeof operators) other than conversions of arithmetic types to integer types (6.6).

I can't find an example of such UB ?

Furthermore I don't understant why a constant expression (evaluated at translation time) does not become an expression evaluated at runtime (instead of being UB).


Solution

  • This is quoted from the informative annex J. To find the actual normative text you have to go the section that the appendix J points at, in this case the definition of integer constant expression C99 6.6:

    An integer constant expression99) 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.

    That text is pretty self-explanatory IMO. That is: whenever syntax or normative text elsewhere requires an integer constant expression, whatever you place at such a location must fulfil the above quoted part, or it is not an integer constant expression but undefined behavior. (Violating a "shall" requirement in normative ISO C text is always UB.)

    I'd expect compilers to be good at giving errors for this since it's compile-time UB.

    For example, this is invalid since an array declaration with static storage duration requires the size to be integer constant expression:

    int a=1;
    static int x [a];
    

    Similarly, int x [1 + 1.0]; would be invalid but int x[1 + (int)1.0]; is ok.