简体   繁体   English

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM