预处理器不执行sizeof()

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

#if内部使用sizeof无法正常工作,为什么?

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

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

但是,当你说:

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

并使用它:

 size(a) 

预处理器执行一个文本替换,交给编译器:

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

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

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

试试这个,你不会得到一个错误:

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

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

这是怎么回事? 事实certificate,除了预处理器宏本身,预处理器(“宏”)表达式中的所有标识符都替换为0.所以上面的#if与说:

 #if Easter_Bunny < 2 

要么

 #if 0 < 2 

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

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

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

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

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

#define仅仅是文本替换。 #if是一个条件预处理器指令,用于计算sizeof()但在预处理时,预处理器不知道sizeof()是什么。 预处理器在词法分析阶段之前运行。

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

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

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

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

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

但是,define语句只是进行文本替换,因此当涉及到编译器时,无论你在’size(x)’的任何地方,你都会有’sizeof(x)/ sizeof(x [0])’,然后这将在编译阶段进行评估…在代码中您有’size(x)’的每个点

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

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