预处理器不执行sizeof()

Fer*_*rdy 15 c c-preprocessor

#if sizeof(int) != 4
/* do something */
Run Code Online (Sandbox Code Playgroud)

在内部使用sizeof #if不起作用#define,为什么?

#define size(x) sizeof(x)/sizeof(x[0]) /*works*/
Run Code Online (Sandbox Code Playgroud)

小智 27

没有什么是邪恶的 - 一切都可能被误用,或者在你的情况下被误解.该sizeof运营商是一个编译器的功能,但是编译器的功能是不提供给预处理器(编译器介入之前运行),因此不能使用#if预处理指令.

但是,当你说:

#define size(x) sizeof(x)/sizeof(x[0])
Run Code Online (Sandbox Code Playgroud)

并使用它:

size(a)
Run Code Online (Sandbox Code Playgroud)

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

sizeof(a)/sizeof(a[0])
Run Code Online (Sandbox Code Playgroud)

  • +1,因为"没有什么是邪恶的".我厌倦了听到"宏是邪恶的".人们用它来称它们为邪恶.:) (18认同)
  • "x是邪恶的"事情是有意夸张的.并不是说任何语言功能实际上都是一个坏主意,应该*永远不会被使用(如果是这样的话,任何理智的语言都会弃用和/或删除所述功能),但更多的是它通常不会 - 所以 - 明显的陷阱,应该限于最适合的情况(和/或应该知道和解释陷阱). (5认同)

cha*_*ley 5

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

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


Dig*_*oss 5

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

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

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

#if sizeof < 2
int f(int x) { return x; }
#endif
Run Code Online (Sandbox Code Playgroud)

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

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

#if Easter_Bunny < 2
Run Code Online (Sandbox Code Playgroud)

要么

#if 0 < 2
Run Code Online (Sandbox Code Playgroud)

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

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

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