预处理器不执行sizeof()

时间:2011-05-21 12:49:37

标签: c c-preprocessor

#if sizeof(int) != 4
/* do something */

在内部#if内使用sizeof无效,#define内部有效,为什么?

#define size(x) sizeof(x)/sizeof(x[0]) /*works*/

9 个答案:

答案 0 :(得分:27)

没有什么是邪恶的 - 一切都可能被误用,或者在你的情况下被误解。 sizeof运算符是编译器功能,但编译器功能不可用于预处理器(在编译器参与之前运行),因此不能在#if预处理器指令中使用。

然而,当你说:

#define size(x) sizeof(x)/sizeof(x[0])

并使用它:

size(a)

预处理器执行文本替换,并将其交给编译器:

sizeof(a)/sizeof(a[0])

答案 1 :(得分:5)

预处理器无法评估sizeof运算符的结果。这是由编译器在预处理器完成很久之后计算的。

由于第二个表达式导致编译时计算,因此它可以工作。第一个是对预处理器进行不可能的测试。

答案 2 :(得分:5)

C“预处理器”宏仅评估常量和其他宏

简短的回答是预处理器表达式只提供对由其他预处理器宏和常量组成的表达式的有意义的评估。

试试这个,你会收到错误:

#if sizeof < 2
int f(int x) { return x; }
#endif

如果生成程序集,您会发现sizeof < 2编译该函数而sizeof >= 2不编译。都不会返回错误。

发生了什么事?事实证明,除了预处理器宏本身之外,预处理器(“宏”)表达式中的所有标识符都替换为0.所以上面的#if与说法相同:

#if Easter_Bunny < 2

#if 0 < 2

这就是为什么在预处理程序表达式中错误地使用sizeof运算符时,实际上不会出现任何错误。

实际上,sizeof是一个运算符,但它也是一个标识符,而且本身不是宏的标识符在预处理程序表达式中都变为0。预处理器至少在概念上运行在编译器之前。它可以将非C语法转换为C,所以在它运行的时候,C程序还没有被解析过。现在还无法引用实际的C对象:它们不存在。

当然,定义的替换文本中的sizeof只是传递给编译器,因为它是使用宏的替换文本。

答案 3 :(得分:4)

#define仅仅是文字替换。作为条件预处理器指令的#if评估sizeof(),但在预处理时,预处理器不知道sizeof()是什么。预处理器在词法分析阶段之前运行。

答案 4 :(得分:3)

sizeof在编译时被替换。 预处理在编译开始之前运行。

答案 5 :(得分:1)

编译器不会触及任何一行。相反,预处理器会翻录文件,用宏替换任何大小(x)的实例。编译器会看到这些替换。

答案 6 :(得分:1)

预处理器不知道sizeof运算符,它只是无法理解它。所以#if不起作用,因为它必须理解它才能工作,因为它是一个条件条件预处理器;它需要知道它是评估为真还是假。

#define无需理解sizeof,因为#define仅用于替换文字。预处理器在源代码中搜索size宏(在#define中定义),并将其替换为定义的内容,在您的情况下为sizeof(x)/sizeof(x[0])

答案 7 :(得分:0)

它不起作用的原因是因为预处理器宏在代码到达编译器之前在传递中被“评估”。所以在if pre-processor指令中,sizeof(int)(实际上是sizeof(int)!= 4)无法评估,因为这是由编译器完成的,而不是预处理器。

但是,define语句只是进行文本替换,所以当涉及到编译器时,无论你有'size(x)',你都会有'sizeof(x)/ sizeof(x [0])'而不是,然后在编译阶段评估那里......代码中你有'size(x)'的每一点

答案 8 :(得分:0)

如果要检查处理器中整数的大小,请在运行预处理器之前使用make系统发现系统上整数的大小,并将其写入头文件,例如: #define SIZEOF_INT 4,请包含此标头文件并执行#if SIZEOF_INT == 4

例如,如果您使用cmake,则可以使用CMAKE_SIZEOF_INT变量,该变量的大小可以放在宏中。