#include <stdio.h>
#define ABS(a) (a) < 0 ? -(a) : (a)
int main(void)
{
printf("%d\n", ABS(-3) + 1);
return 0;
}
来自Herbert Schildt的书中的这段代码片段看起来会产生输出4
,但它实际上会打印3
。为什么呢?
我该如何解决?
答案 0 :(得分:5)
正确的方法是使用inline
函数,对于要支持的每种类型都使用_Generic
大小写。否则,您评估a
两次。
代替你可以通过在宏中括起表达式来修复它。确实防止出现这种问题总是一个好主意。
#define ABS(a) ((a) < 0 ? -(a) : (a))
出现问题是因为X ? Y : Z + 1
表示X ? Y : (Z + 1)
。
答案 1 :(得分:4)
扩展您的宏:
#define ABS(a) (a) < 0 ? -(a) : (a)
printf("%d\n", ABS(-3) + 1);
printf("%d\n", (-3) < 0 ? -(-3) : (-3) + 1); // you can get this with **gcc -E source.c
printf("%d\n", (-3) < 0 ? 3 : -2); //read about precedence to understand this step.
printf("%d\n", 3);
这是为什么要打印3
的分步说明。您需要使用适当的括号来修复它。
答案 2 :(得分:2)
与函数不同,宏在遇到它们的地方展开。 因此在此代码中
printf("%d\n", ABS(-3) + 1);
当遇到ABS(-3)时,它被扩展,即
printf("%d\n", (-3) < 0 ? -(-3) : (-3) + 1);
因此,expressoin是真的, - ( - 3)被评估(在你的情况下)。如果表达式被评估为假(例如),那么结果将是(-3)+1,即-2。
解决此问题,而不是
#define ABS(a) (a) < 0 ? -(a) : (a)
写
#define ABS(a) ((a) < 0 ? -(a) : (a))
答案 3 :(得分:1)
修复括号 #define ABS(a)(((a)&lt; 0)? - (a):( a))