Pav*_*kin 5 c language-lawyer constant-expression c-preprocessor preprocessor-directive
C11,6.10.1 有条件包含,约束,1(强调):
控制条件包含的表达式应为整数常量表达式
C11,6.6 常量表达式,6(强调):
整数常量表达式117)应具有整数类型,并且只能具有整数常量、枚举常量、字符
sizeof常量、结果为整数常量的表达式、_Alignof表达式以及作为强制转换的直接操作数的浮点常量的操作数。
$ 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
Run Code Online (Sandbox Code Playgroud)
这里(int)1.0是整型常量表达式。它具有整数类型并具有操作数,该操作数是浮点常量,是强制转换的立即操作数。但是,每个gcc代码都是无效的。
这意味着 6.10 预处理指令中使用的“整数常量表达式”受到限制 [1]?标准中有明确规定吗?
[1] 例如,“除了sizeof结果为整数常量、_Alignof表达式和作为强制转换的直接操作数的浮点常量的表达式”
您需要完整地查看 6.10.1p1:
\n\n\n控制条件包含的表达式应为整数常量表达式,但以下情况除外: 标识符(包括在词法上与关键字相同的标识符)按如下所述进行解释;166),并且它可能包含\n以下形式的一元运算符表达式
\nRun Code Online (Sandbox Code Playgroud)\ndefined identifier\n或者
\nRun Code Online (Sandbox Code Playgroud)\ndefined ( identifier )\n如果标识符当前定义为宏名称(即,如果它是预定义的,或者它是预处理指令的主题,而没有具有
\n#define相同#undef主题标识符的中间指令),则计算结果为 1,如果它不是。
其中脚注 166 指出:
\n\n\n\n
\n- 因为控制常量表达式是在转换阶段 4 期间计算的,所以所有标识符要么是宏名称,要么不是宏名称\n\xe2\x80\x94,根本没有关键字、枚举常量等。
\n
因此,预处理器不会将关键字int视为关键字,而是将其视为标识符,从而视为宏名称。这会导致语法无效并导致错误。
这意味着指令中不允许使用涉及强制转换、sizeof或 的整数常量表达式。_Alignof#if