奇怪的宏定义问题

我想在编译时根据另一个宏的值定义一个宏。 但是,此代码未按预期执行:

#include  #include  #include  #define SIXTEEN 16 #define TWO (SIXTEEN % 8 == 0)? (SIXTEEN / 8) : ((SIXTEEN / 8) + 1) int main(); int main() { printf("max = %d\n", TWO); int i; for (i = 0; i < TWO; i++) { printf("%d\n", i); } return 0; } 

这打印:

 max = 2 0 1 2 ... 

并继续直到终止,当它应该打印简单:

 max = 2 0 1 

并退出。

如果我这样做,它的工作原理:

 #define TWO 2 

我认为这是宏的定义的一个问题…但是,如果我使用原始的#define执行以下操作,它似乎工作:

 ... int count = TWO; for (i = 0; i < count; i++) { ... 

谁能解释一下这里发生了什么?

问题是令牌TWO被您定义宏的令牌所取代,因此:

 i < TWO 

成为这个:

 i < (SIXTEEN % 8 == 0)? (SIXTEEN / 8) : ((SIXTEEN / 8) + 1) 

由于运算符优先级,因此读为:

 (i < (SIXTEEN % 8 == 0)) ? (SIXTEEN / 8) : ((SIXTEEN / 8) + 1) 

您需要额外的括号,以便当TWO替换为替换列表时,您将获得所需的结果:

 #define TWO ((SIXTEEN % 8 == 0)? (SIXTEEN / 8) : ((SIXTEEN / 8) + 1)) ^ ^ 

使用宏时,最好在任何地方使用括号,以确保结果符合您的预期。

始终将宏括在括号中,因为您并不总是知道将使用它的上下文 – 可能会发生相邻运算符具有更高优先级并且宏无法正确计算的情况。

如果# #define符号是单个标记,例如5"hello world"#define使用括号是合理的。

如果考虑使用作为表达式而不仅仅是单个标记的参数调用宏,请将该参数的每个匹配项括在括号中,原因与上述相同。

要避免的另一件事是传递具有副作用的表达式作为宏参数。 如果在其定义中多次引用相应的宏参数,则将不止一次执行评估,这通常不是所期望的。

展开宏,并在宏扩展后查看for循环:

 for (i = 0; i < (16 % 8 == 0)? (16 / 8) : ((16 / 8) + 1); i++) 

看到? i < (16 % 8 == 0)?:运算符的条件。 你需要在TWO的定义周围加上一对括号。