[英]What is the correct way to define this C macro?
#include <stdio.h>
#define ABS(a) (a) < 0 ? -(a) : (a)
int main(void)
{
printf("%d\n", ABS(-3) + 1);
return 0;
}
This code snippet, from Herbert Schildt's book, looks like it will produce the output 4
but it actually prints 3
. 这段代码片段来自Herbert Schildt的书,看起来它会产生输出4
但实际上它打印3
。 Why? 为什么?
How do I fix it? 我如何解决它?
The correct way is to use an inline
function, with a _Generic
case for each type you want to support. 正确的方法是使用inline
函数,对于要支持的每种类型都使用_Generic
大小写。 Otherwise you evaluate a
twice. 否则,你评估a
两次。
In lieu of that you can fix it by parenthesizing the expression in the macro. 代替它,您可以通过在宏中括起表达式来修复它。 That is always a good idea to prevent exactly this sort of problem. 这一直是防止这类问题的好主意。
#define ABS(a) ((a) < 0 ? -(a) : (a))
The problem comes about because X ? Y : Z + 1
问题来自于X ? Y : Z + 1
X ? Y : Z + 1
means X ? Y : (Z + 1)
X ? Y : Z + 1
表示X ? Y : (Z + 1)
X ? Y : (Z + 1)
. X ? Y : (Z + 1)
。
Expand your macro: 扩展您的宏:
#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);
This is the step by step explanation of why is printing 3
. 这是为什么要打印3
逐步解释。 You need to fix it using the appropriate parenthesis. 您需要使用适当的括号来修复它。
Unlike functions macros are expanded in the place where they are encountered. 与函数不同,宏在遇到它们的地方展开。 Therefore in this code 因此在此代码中
printf("%d\n", ABS(-3) + 1);
when ABS(-3) is encountered it is expanded, ie 当遇到ABS(-3)时,它被扩展,即
printf("%d\n", (-3) < 0 ? -(-3) : (-3) + 1);
So the expressoin is true and -(-3) is evaluated (in your case). 所以expressoin是真的, - ( - 3)被评估(在你的情况下)。 If the expression was evaluated to false (say) then the result would have been (-3)+1 which is -2. 如果表达式被评估为假(例如),那么结果将是(-3)+1,即-2。
To fix this, instead of 解决这个问题,而不是
#define ABS(a) (a) < 0 ? -(a) : (a)
write 写
#define ABS(a) ((a) < 0 ? -(a) : (a))
修正括号#define ABS(a)(((a)<0)? - (a):( a))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.