我想在编译时根据另一个宏的值定义一个宏。但是,此代码未按预期执行:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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++) {
...
有谁能解释这里发生了什么?
答案 0 :(得分:11)
问题是令牌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))
^ ^
使用宏时,最好在任何地方使用括号,以确保结果符合您的预期。
答案 1 :(得分:2)
始终将宏括在括号中,因为您并不总是知道将使用它的上下文 - 可能会发生相邻运算符具有更高优先级并且宏将无法正确计算。
如果#define
'd符号是单个标记,例如5
或"hello world"
,则不使用括号是合理的。
如果考虑使用表达式而不仅仅是单个标记调用宏,请将该参数的每个匹配项括在括号中,原因与上述相同。
要避免的另一件事是传递具有副作用的表达式作为宏参数。如果相应的宏参数在其定义中被多次引用,则评估将不止一次执行,而这通常不是所期望的。
答案 2 :(得分:1)
展开宏,并在宏扩展后查看for
循环:
for (i = 0; i < (16 % 8 == 0)? (16 / 8) : ((16 / 8) + 1); i++)
请参阅? i < (16 % 8 == 0)
是?:
运算符的条件。您需要在TWO
的定义周围添加一对括号。