只计算一次宏参数

Evaluate macro parameter only once

我需要编写一个宏来捕获长度为 n 的数组的任何无效索引 i。这是我到目前为止得到的:

#define TRAP(i, n) (((unsigned int) (i) < (n))? (i): (abort(), 0))

然而,这个定义的问题是索引表达式 i 被计算了两次;在表达式 a[TRAP(f(), n)],例如,f 可能会产生副作用或需要很长时间才能执行。我不能引入临时变量,因为宏需要扩展为表达式。此外,将 TRAP 定义为普通函数意味着 运行 时间开销,并使编译器更难优化陷阱。

有没有办法重写 TRAP 以便 i 只计算一次?

编辑:我使用的是 ANSI C89

您可以计算一次,然后使用结果,方法如下:

#define TRAP2(i, n) ({unsigned int _i = (i); _i < (n)? _i: (abort(), 0);})

这是一个 gcc 特定的解决方案,当用作赋值的 RHS 时将编译。它定义了一个(非常)局部变量,它可能隐藏了另一个变量的先前定义,但这并不重要,只要您不尝试在宏中使用先前版本。但正如人们所说,为什么首先要这样做?

当索引表达式不包含函数调用时使用宏TRAP并使用(非宏)函数trap当它发生时。这样函数调用开销只发生在后一种情况下。