min/max函数的无辜宏定义有什么问题?

Spa*_*ler 2 c macros

该文件windef.h使用宏定义最小/最大函数,如下所示:

#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
Run Code Online (Sandbox Code Playgroud)

但是,已经注意到这样一个定义:

  1. 遭受双重评估.
  2. 不安全.

我不明白的是:

  1. 为什么/哪里有双重评估?
  2. 琐碎的重新定义如何__typeof__ (a) _a = (a); __typeof__ (b) _b = (b);有助于类型安全,为什么在这种情况下不进行双重评估?

Lun*_*din 8

为什么/哪里有双重评估?

理解这一点的最简单方法是运行以下代码:

#include <stdio.h>

#define max(a,b) ((a)>(b)?(a):(b))

int f1 (void) 
{ 
  printf("%s executed.\n", __func__);
  return 1; 
}

int f2 (void) 
{ 
  printf("%s executed.\n", __func__);
  return 2; 
}

int main (void)
{
  printf("Max: %d", max(f1(), f2()) );
}
Run Code Online (Sandbox Code Playgroud)

输出:

f1 executed.
f2 executed.
f2 executed.
Max: 2
Run Code Online (Sandbox Code Playgroud)

函数f2()被调用两次,因为宏参数b被计算两次.


琐碎的重新定义如何__typeof__ (a) _a = (a); __typeof__ (b) _b = (b);有助于类型安全,为什么在这种情况下不进行双重评估?

因为该代码创建了两个临时变量并存储了评估结果,每个变量一次.

请注意,__typeof__还有({ ... })语法不是标准的C,应该避免.链接接受的答案中的宏非常难看,而不是我推荐的.

理智的解决方案是不使用宏,但功能:

static inline int max (int a, int b)
{
  return a > b ? a : b;
}
Run Code Online (Sandbox Code Playgroud)

注意与宏观混乱相比,代码的可读性.

如果由于某种原因未知必须使用宏,请坚​​持标准C,如下所示:https://stackoverflow.com/a/30918240/584518

  • @chux确实,宏允许`max(苹果,橘子)`:) (2认同)