以下表达式究竟计算了什么?
#define SIGN(x) ((x < 0) ? -1 : (x > 0))
如果x为零,小于零,大于零,会产生什么? 我想我知道答案,但我想检查清楚......
谢谢
编辑:添加了缺少的括号 编辑:更多信息here
答案 0 :(得分:2)
它完全符合你的想法,负数为-1
,零为0
,正数为1
。
但是,您通常应该避免使用类似函数的宏,因为例如,如果您尝试计算SIGN(value++)
,它们不会执行您期望的操作。由于它们是简单的文本替换,因此可以解决:
((value++ < 0) ? -1 : (value++ > 0)
你只需使用真正的函数,并让编译器内联它们,如果它决定它是值得的,那就更好了。您还可以使用inline
关键字向编译器建议内联它,但请记住 是一个建议。
答案 1 :(得分:2)
首先,宏不计算任何东西。它被替换为源代码,扩展,并生成结果文本。生成的文本取决于您使用宏的方式,尤其取决于您给出的参数。
其次,宏缺少一个结束语,所以它可能不会给你一个有意义的表达式来编译。
第三,即使你添加缺乏的paren:
#define SIGN(x) ((x < 0) ? -1 : (x > 0))
如果以非最简单的方式使用宏,则可能会出现意外结果。例如,
SIGN(a ^ b)
会导致
((a ^ b < 0) ? -1 : (a ^ b > 0))
在C和C ++中解释为
((a ^ (b < 0)) ? -1 : (a ^ (b > 0)))
当然不我们打算做什么。
您应该添加括号以避免不需要的运算符绑定 - 对于:
#define SIGN(x) (((x) < 0) ? -1 : ((x) > 0))
上面的例子将产生一个明智的表达
(((a ^ b) < 0) ? -1 : ((a ^ b) > 0))
但是,如果替换为x
的表达式包含函数调用,则在加号或减号运算符的情况下仍然不能保护您免受不必要的双增/减,或者双重执行函数。
答案 2 :(得分:1)
那个宏有一个假的括号。 它看起来像是signum函数的一个实现,它根据参数的值返回-1,1或0。
为了安全起见并编写C ++代码,这是谨慎的 用模板替换宏,类似于
template <class T>
int SIGN( T x )
{
return (x < T(0)) ? -1 : (x > T(0));
}
第一个比较是trenary运算符的参数?:。如果表达式求值为真,则三元将返回-1,即x小于0,否则它将返回x> 1的结果。 T(0)。 如果x等于0,该表达式将计算为0,否则将评估为1。
请注意,我的实现并不理想,你可以在其他地方找到更好的实现。 另一种表达方式可以是:
return (T(0)<x) - (T(0)>x);
对于实现某些CPU指令的平台,这可能更有效
答案 3 :(得分:0)
如果仅将值与值一起使用而不是宏将生成-1,0,1的表达式,否则可能会出现严重问题。棘手的部分是(x> 0)。让我们阅读标准:
5.9关系运算符[expr.rel]
运营商&lt; (小于),&gt; (大于),&lt; =(小于或等于 to)和&gt; =(大于或等于)所有产生false或true。该 结果的类型是bool。
和
3.9.1基本类型[basic.fundamental]
bool类型的值为true或false。 bool类型的值参与整体促销(4.5)。
因此x> 0是true
或false
。
4.5整体促销[conv.prom]
bool类型的prvalue可以转换为int类型的prvalue,false变为零,true变为1。
并分别提升为1
或0
。