奇怪的宏定义问题
我想在编译时根据另一个宏的值定义一个宏。 但是,此代码未按预期执行:
#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
的定义周围加上一对括号。