C11, 6.10.1 Conditional inclusion, Constraints, 1 (emphasis added):
The expression that controls conditional inclusion shall be an integer constant expression
C11, 6.6 Constant expressions, 6 (emphasis added):
An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants,
sizeof
expressions whose results are integer constants,_Alignof
expressions, and floating constants that are the immediate operands of casts.
$ cat t333.c
#if (int)1.0
#endif
$ gcc t333.c -std=c11 -pedantic -c
t333.c:1:10: error: missing binary operator before token "1.0"
1 | #if (int)1.0
Here (int)1.0
in the integer constant expression. It has integer type and has operand, which is floating constant that is the immediate operand of cast. However, per gcc
the code is invalid.
Meaning that "integer constant expression" used in 6.10 Preprocessing directives is limited [1]? Is it explicitly specified in the standard?
[1] For example, "except sizeof
expressions whose results are integer constants, _Alignof
expressions, and floating constants that are the immediate operands of casts"
You need to look at 6.10.1p1 in its entirety:
The expression that controls conditional inclusion shall be an integer constant expression except that: identifiers (including those lexically identical to keywords) are interpreted as described below;166), and it may contain unary operator expressions of the form
defined identifier
or
defined ( identifier )
which evaluate to 1 if the identifier is currently defined as a macro name (that is, if it is predefined or if it has been the subject of a
#define
preprocessing directive without an intervening#undef
directive with the same subject identifier), 0 if it is not.
Where footnote 166 states:
- Because the controlling constant expression is evaluated during translation phase 4, all identifiers either are or are not macro names — there simply are no keywords, enumeration constants, etc.
So the keyword int
is not treated as a keyword by the preprocessor but instead as an identifier and therefore a macro name. This results in invalid syntax that causes an error.
This means that integer constant expressions that involve either a cast, sizeof
, or _Alignof
are not allowed in an #if
directive.