Reputation: 569
What the following expression computes, exactly?
#define SIGN(x) ((x < 0) ? -1 : (x > 0))
what yields if x is zero, less than zero, more than zero? I guess I know the answer, but I'd like to check for clarity...
Thank you
EDIT: added missing parenthesis EDIT: more info here
Upvotes: 0
Views: 825
Reputation: 36401
If you use it with values only and not expressions that macro will produce -1, 0, 1, otherwise you may have serious problems. The tricky part is (x>0). Lets read the standard:
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.
and
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).
Thus x>0 is either true
or false
.
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.
and is promoted to either 1
or 0
(respectively).
Upvotes: 0
Reputation: 9570
First, the macro doesn't compute anything. It is substituted into a source code, expanded, and the resulting text gets compiled. What the resulting text is, depends on the way you use the macro, especially on what parameter you give.
Second, the macro lacks one closing paren, so it probably would not give you a meaningful expression to be compiled.
Third, even when you add the lacking paren:
#define SIGN(x) ((x < 0) ? -1 : (x > 0))
it is possible you get unexpected results if you use the macro in a non-simplest way. For example,
SIGN(a ^ b)
would result in
((a ^ b < 0) ? -1 : (a ^ b > 0))
which is interpreted in C and C++ as
((a ^ (b < 0)) ? -1 : (a ^ (b > 0)))
which certainly is not what we intend.
You should add parentheses to avoid unwanted operators binding – for:
#define SIGN(x) (((x) < 0) ? -1 : ((x) > 0))
the above example will yield a sensible expression
(((a ^ b) < 0) ? -1 : ((a ^ b) > 0))
but that still doesn't protect you against unwanted double increment/decrement in case of plus-plus or minus-minus operators or double execution of a function in case the expression substituted for x
contains a function call.
Upvotes: 2
Reputation: 14614
That macro got a stray parenthesis. It looks like it is meant to be an implementation of signum function, which returns -1, 1 or 0 depending on value of argument.
For sake of being safe and writing C++ code, it is prudent to replace macro by template, similar to
template <class T>
int SIGN( T x )
{
return (x < T(0)) ? -1 : (x > T(0));
}
First comparision is argument of trenary operator ?:. Ternary would return -1 if expression evaluates to true , i.e. x is less than 0, otherwise it would return result of x > T(0). That expression would evaluated to 0 if x equals to 0, otherwise it would be evaluated to 1.
Note that my implementation is not ideal, you can find better implementation elsewhere on SO. An alternative expression can be:
return (T(0)<x) - (T(0)>x);
Which may be more effective with platforms that implement certain CPU instructions
Upvotes: 1
Reputation: 881663
It does exactly what you probably think it does, gives -1
for negative numbers, 0
for zero, and 1
for positive numbers.
However, you should generally avoid function-like macros since they will not do what you expect if, for example, you try to calculate SIGN(value++)
. Since they're simple text substitutions, that would resolve to:
((value++ < 0) ? -1 : (value++ > 0)
You're far better off just using real functions and letting the compiler inline them if it decides it's worth it. You can also suggest to the compiler that inlining it, with the inline
keyword, but keep in mind it is a suggestion.
Upvotes: 2