定义此C宏的正确方法是什么?

时间:2015-07-21 04:21:15

标签: 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。为什么呢?

我该如何解决?

4 个答案:

答案 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))