5

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"

pmor
  • 5,392
  • 4
  • 17
  • 36

1 Answers1

8

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:

  1. 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.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • What about C++: `echo "#if 1.0" | g++ -xc++ - -std=c++11 -pedantic -c` leads to `error: floating constant in preprocessor expression`, however, I cannot see where C++ standard prohibits using floating-point literal in the expression that controls conditional inclusion. Does it prohibit? Where? – pmor Jan 31 '22 at 15:38
  • @pmor Although your question relates to language which inherits many these features from C, it's has a completely different stardard document. You should ask completely new question for it. – user694733 Feb 01 '22 at 10:40
  • @user694733 Indeed. [Asked](https://stackoverflow.com/q/70943108/1778275). – pmor Feb 01 '22 at 15:27