#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
。为什么?什么是定义这个C宏的正确方法?
我该如何解决?
#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
。为什么?什么是定义这个C宏的正确方法?
我该如何解决?
展开宏:
#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
。您需要使用适当的括号修复它。
正确的方法是使用inline
函数,对于您要支持的每种类型,使用_Generic
大小写。否则你评估a
两次。
代替你可以通过在宏中加入表达式来修复它。这总是一个好主意,以防止这类问题。
#define ABS(a) ((a) < 0 ? -(a) : (a))
问题就来了,因为有关机构X ? Y : Z + 1
X ? Y : (Z + 1)
。
该解决方案有效。你能告诉我为什么它变成了'Z + 1'吗? '+ 1'不是调用ABS()的一部分吧? – rohithpr
@ praroh1这就是问题所在,宏不是函数,也不会被调用,它们会被代入代码中。 printf(“%d \ n”,(-3)<0? - ( - 3):(-3)+ 1);' - 因此,在'printf'调用看起来像这样预处理后: Z + 1'来自。 – jduncanator
@jduncanator - 啊!现在有道理。谢谢。 – rohithpr
修复括号 的#define ABS(一)(((一)< 0) - (一):(一))
与函数宏不同的是它们遇到的地方被扩展。 因此,在这段代码
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))
尝试扩大自己的宏,看看你会得到什么。请记住,宏不是函数。 – godel9
宏定义的一般规则是将整个事物括起来,并在每次使用宏参数时使用parens - 除非有特定的原因(你可以解释)不要。 –
接下来的问题是'abs( - b)'也会给出错误的答案。 – Jasen