使用宏进行符号计算

Sign computation with a macro

以下表达式计算的究竟是什么?

#define SIGN(x) ((x < 0) ? -1 : (x > 0))

如果 x 为零、小于零、大于零,结果是什么? 我想我知道答案,但我想检查清楚...

谢谢

编辑:添加了缺少的括号 编辑:更多信息 here

它的作用与您可能认为的作用完全相同,-1表示负数,0表示零,1表示正数。

但是,您通常应该避免使用 function-like 宏,因为它们 不会 执行您期望的操作,例如,如果您尝试计算 SIGN(value++)。由于它们是简单的文本替换,因此将解析为:

((value++ < 0) ? -1 : (value++ > 0)

你最好只使用 real 函数并让编译器在认为值得时内联它们。您还可以建议编译器使用 inline 关键字内联它,但请记住它 一个建议。

那个宏有一个杂散的括号。 它看起来像是 signum 函数的实现,returns -1、1 或 0 取决于参数的值。

为了安全起见,写C++代码,慎重 用模板替换宏,类似于

template <class T>
int SIGN( T x )
{
 return (x < T(0)) ? -1 : (x > T(0));
}

首先比较的是三元运算符的参数?:。如果表达式的计算结果为 true,即 x 小于 0,则三元将 return -1,否则它将 return x > T(0) 的结果。 如果 x 等于 0,则该表达式将计算为 0,否则将计算为 1。

请注意,我的实现并不理想,您可以在 SO 的其他地方找到更好的实现。 替代表达式可以是:

return (T(0)<x) - (T(0)>x);

对于实现某些 CPU 指令的平台,这可能更有效

首先,宏不计算任何东西。它被代入源代码、扩展,并编译生成的文本。结果文本是什么,取决于您使用宏的方式,尤其是您提供的参数。

其次,该宏缺少一个右括号,因此它可能不会为您提供一个有意义的表达式进行编译。

第三,即使你添加了缺少的括号:

#define SIGN(x) ((x < 0) ? -1 : (x > 0))

如果您以 non-simplest 的方式使用宏,您可能会得到意想不到的结果。例如,

SIGN(a ^ b)

会导致

((a ^ b < 0) ? -1 : (a ^ b > 0))

在 C 和 C++ 中解释为

((a ^ (b < 0)) ? -1 : (a ^ (b > 0)))

这肯定不是我们想要的。

您应该添加括号以避免不必要的运算符绑定 – for:

#define SIGN(x) (((x) < 0) ? -1 : ((x) > 0))

以上示例将产生一个合理的表达式

(((a ^ b) < 0) ? -1 : ((a ^ b) > 0))

但这仍然不能保护您免受 plus-plus 或 minus-minus 运算符的不必要的双重 increment/decrement 或函数的双重执行,以防表达式替换为 x 包含函数调用。

如果您仅将它用于值而不是表达式,该宏将产生 -1、0、1,否则您可能会遇到严重的问题。棘手的部分是 (x>0)。让我们阅读标准:

5.9 Relational operators [expr.rel]

The operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) all yield false or true. The type of the result is bool.

3.9.1 Fundamental types [basic.fundamental]

Values of type bool are either true or false. Values of type bool participate in integral promotions (4.5).

因此 x>0 是 truefalse

4.5 Integral promotions [conv.prom]

A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.

并晋升为 10(分别)。