产生错误数字的宏

macro producing wrong number

我不明白为什么下面的代码打印 2 而不是 1...

#include <stdio.h>
#define ABS(x) ((x) < 0) ? -(x) : (x)
int main()
{
    printf("%d", ABS(ABS(-2)-(ABS(-3))));
    return 0;
}

这个问题出现在我们的考试中,我回答的输出是 1,但编译后我得到 2...谁能解释一下表达式的实际作用...提前致谢。

括号有问题。如果展开宏,您将得到一个复杂的嵌套三元运算,其计算结果为 2(请参阅更新中的展开)。为了获得理想的结果,用括号将宏括起来。

更新:手动扩容:

ABS(ABS(-2)-(ABS(-3)))

扩展为:

((ABS(-2)-(ABS(-3))) < 0) ? -(ABS(-2)-(ABS(-3))) : (ABS(-2)-(ABS(-3)))

ABS(-3) 到处都是括号,所以它被安全地评估为 3,所以不需要扩展它。所以我们最终得到:

(( ((-2) < 0) ? -(-2) : (-2) - 3) < 0) ? -(ABS(-2)-3) : (ABS(-2)-3)

(ABS(-2)-3) 将扩展为

((-2) < 0) ? -(-2) : (-2) - 3 = 2

整体评价: (( true ? 2 : -5 < 0) ? -2 : 2

(2 < 0) ? -2 : 2 = 2 并且是观察到的结果,希望有借鉴意义

这是eno

你忘记了外括号,试试这个:

#define ABS(x) (((x) < 0) ? -(x) : (x))
#include <stdio.h>
#define ABS(x) ((x) < 0) ? -(x) : (x))
int main()
{
    printf( "%d", ABS( ABS(-2) - ABS(-3) ) );
    return 0;
}

您忘记了 #define 中的右括号 )

另外,return需要小写

我放了空格,这样你可以更清楚地看到分组。

http://coliru.stacked-crooked.com/a/59700f453a1dcaf9 中使用编译选项 -E

gcc 预处理器已解决此问题:

printf("%d\n", ABS(ABS(-2)-(ABS(-3))));

对此:

printf("%d\n", ((((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) < 0) ? -(((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) : (((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))));

自己检查一下

您需要在 ABS 定义的表达式周围加上括号。而不是

#define ABS(x) ((x) < 0) ? -(x) : (x)

你需要:

#define ABS(x) (((x) < 0) ? -(x) : (x))
               ^----------------------^

没有它,表达式 ABS(ABS(-2)-(ABS(-3))) 扩展为:

((((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) < 0) ?  -(((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3))) : (((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ? -(-3) : (-3)))

这将是一项艰难的分析,以了解哪里出了问题。但是,如果您查看表达式的开头,您会发现第一项与第二项相吻合。

((-2) < 0) ? -(-2) : (-2)-(((-3) < 0) ...
                         ^^ (-2) Runs into the next term

表达式的值很难预测。如果在宏定义的表达式周围添加括号,您将看到:

( (((-2) < 0) ? -(-2) : (-2)) - ( (((-3) < 0) ...
  ^ ------ one term ------- ^ There is no running in to the next term.

让我们手动展开该宏:

ABS(-3) == ((-3) < 0) ? -(-3) : (-3)
ABS(-2) == ((-2) < 0) ? -(-2) : (-2)

ABS(-2) - ABS(-3) ==
  ((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)

现在我们遇到了一个问题:二进制 - 的优先级高于 ?:,因此上面的内容被 解析 为:

((-2) < 0) ? -(-2) : 
  ((-2) - ((-3) < 0) ? -(-3) : (-3))

由于 (-2) < 0 为真,我们评估 -(-2)。那么:

ABS( ABS(-2) - ABS(-3) ) ==
  ((((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)) < 0 ?
    -(((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)) :
    (((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3))

我们已经确定

((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3)

的计算结果为 2,因此表达式

(((-2) < 0) ? -(-2) : (-2) - ((-3) < 0) ? -(-3) : (-3))

得到评估,你猜怎么着?它的计算结果为 2.

您需要做的是如下更改您的宏:

ABS(x) ( (x) < 0 ? -(x) : (x) )

然后一切展开为

ABS(-3) == ((-3) < 0 ? -(-3) : (-3))
ABS(-2) == ((-2) < 0 ? -(-2) : (-2))

ABS(-2) - ABS(-3) ==
  ((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))

ABS(ABS(-2) - ABS(-3)) ==
  (((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3)) < 0 ?
    -(((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))) :
     ((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))

这次,

(((-2) < 0 ? -(-2) : (-2)) - ((-3) < 0 ? -(-3) : (-3))

计算为 -1

剩下的应该从这里清楚了。

正是出于这个原因,您应该始终将表达式宏体包裹在一对外括号中。