Are the integer comparison operators short circuited in C++? - c++

Like the title states, are the integer (or any numerical datatypes like float etc.) comparison operators (==, !=, >, >=, <, <=) short circuited in C++?

They can't short circuit. To know if x == y, x != y, etc are true or false you need to evaluate both, x and y. Short circuiting refers to logical boolean operators && and ||. Logical AND is known to be false if the first argument is false and Logical OR is known to be true if the first argument is true. In these cases you don't need to evaluate the second argument, this is called short circuiting.
Edit: this follows the discussions for why x >= y don't short circuit when the operands are unsigned ints and x is zero:
For logical operands short circuiting comes for free and is implementation neutral. The machine code for if(f() && g()) stmt; is likely to look similar to this:
call f
test return value of f
jump to next on zero
call g
test return value of g
jump to next on zero
execute stmt
next: ...
To prevent short circuiting you actually need to do the computation of the result of the operator and test it after that. This takes you a register and makes the code less efficient.
For non-logical operators the situation is the opposite. Mandating short circuiting implies:
The compiler can't choose an evaluation of the expression that uses a minimum number of registers.
The semantics may be implementation defined (or even undefined) for many cases, like when comparing with maximum value.
The compiler needs to add an additional test/jump. For if(f() > g()) stmt; the machine code will look like this:
call f
mov return value of f to R1
test return value of f
jump to next on zero
call g
compare R1 with return value of g
jump to next on less-than equal
execute stmt
next: ...
Note how the first test and jump are just unnecessary otherwise.

No. The comparison operators require both operands to evaluate the correct answer. By contrast, the logical operators && and || in some cases don't need to evaluate the right operand to get the right answer, and therefore do "short-circuit".

No, how could they be. In order to check whether 1 == 2 you have to inspect both the 1 and the 2. (Ofcoruse, a compiler can do a lot of reordering, static checking, optimizations, etc. but that's not inherit to c++)

How would that work? Short-circuiting means you can avoid evaluating the RHS based solely on the result of evaluating the LHS.
e.g.
true || false
doesn't need to evaluate the RHS because true || x is true no matter what x turns out to be.
But this won't work for any of the comparisons that you list. For example:
5 == x
How can you ever know the result of the expression without knowing x?

Related

In what order are expressions in an `if` condition evaluated? [duplicate]

if(a && b)
{
do something;
}
is there any possibility to evaluate arguments from right to left(b -> a)?
if "yes", what influences the evaluation order?
(i'm using VS2008)
With C++ there are only a few operators that guarantee the evaluation order
operator && evaluates left operand first and if the value is logically false then it avoids evaluating the right operand. Typical use is for example if (x > 0 && k/x < limit) ... that avoids division by zero problems.
operator || evaluates left operand first and if the value is logically true then it avoids evaluating the right operand. For example if (overwrite_files || confirm("File existing, overwrite?")) ... will not ask confirmation when the flag overwrite_files is set.
operator , evaluates left operand first and then right operand anyway, returning the value of right operand. This operator is not used very often. Note that commas between parameters in a function call are not comma operators and the order of evaluation is not guaranteed.
The ternary operator x?y:z evaluates x first, and then depending on the logical value of the result evaluates either only y or only z.
For all other operators the order of evaluation is not specified.
The situation is actually worse because it's not that the order is not specified, but that there is not even an "order" for the expression at all, and for example in
std::cout << f() << g() << x(k(), h());
it's possible that functions will be called in the order h-g-k-x-f (this is a bit disturbing because the mental model of << operator conveys somehow the idea of sequentiality but in reality respects the sequence only in the order results are put on the stream and not in the order the results are computed).
Obviously the value dependencies in the expression may introduce some order guarantee; for example in the above expression it's guaranteed that both k() and h() will be called before x(...) because the return values from both are needed to call x (C++ is not lazy).
Note also that the guarantees for &&, || and , are valid only for predefined operators. If you overload those operators for your types they will be in that case like normal function calls and the order of evaluation of the operands will be unspecified.
Changes since C++17
C++17 introduced some extra ad-hoc specific guarantees about evaluation order (for example in the left-shift operator <<). For all the details see https://stackoverflow.com/a/38501596/320726
The evaluation order is specified by the standard and is left-to-right. The left-most expression will always be evaluated first with the && clause.
If you want b to be evaluated first:
if(b && a)
{
//do something
}
If both arguments are methods and you want both of them to be evaluated regardless of their result:
bool rb = b();
bool ra = a();
if ( ra && rb )
{
//do something
}
In this case, since you're using &&, a will always be evaluated first because the result is used to determine whether or not to short-circuit the expression.
If a returns false, then b is not allowed to evaluate at all.
Every value computation and side effect of the first (left) argument of the built-in logical AND operator && and the built-in logical OR operator || is sequenced before every value computation and side effect of the second (right) argument.
Read here for a more exhaustive explanation of the rules set:
order evaluation
It will evaluate from left to right and short-circuit the evaluation if it can (e.g. if a evaluates to false it won't evaluate b).
If you care about the order they are evaluated in you just need to specify them in the desired order of evaluation in your if statement.
The built-in && operator always evaluates its left operand first. For example:
if (a && b)
{
//block of code
}
If a is false, then b will not be evaluated.
If you want b to be evaluated first, and a only if b is true, simply write the expression the other way around:
if (b && a)
{
//block of code
}

The order of evaluation of equality operator in C++

Recently I have read some chapters C++ Primer, there is one things which made me confused.
The book says:
There are four operators that do guarantee the order in which operands are evaluated.
the logical AND (&&) operator,
the logical OR (||) operator,
the conditional (? :) operator,
and the comma (,) operator.
And then I saw these codes:
if (val == true) { /* ... */ } // true only if val is equal to 1!
Then the book explain:
If val is not a bool, then true is converted to the type of val before the == operator is applied.
That is, when val is not a bool, it is as if we had written
if (val == 1) { /* ... */ }
Here is my question:
Why is the bool type true converted to arithmetic type, not the val instead? Is it involve the order of evaluation of equality operator?
Just as the book says only four operators guarantee the order, not including equality operator. So the result of the expression above should be undefined, am I right? If not, what it should be?
Looking forward to your reply. Thanks in advance.
It has nothing to do with the order of evaluation. The comparison operators always perform the usual arithmetic conversions on their operands. These conversions apply equally to both operands (although the order is unspecified). In the case in which a bool is being compared to another integral type, the operand of type bool is always promoted to int first.
Relational operators such as ==, <=, etc., always produce boolean results. This is part of a set of rules known as "the usual arithmetic conversions".
Which side of the operator gets converted to what and in what order is somewhat esoteric and would concern compiler writers. It would be beyond the scope of a programmer.
In the condition of the if statement there are two different types
These are:
int
bool
In c++ types such as:
bool
char
short
are always converted to int first, hence in the condition of the if, true which is bool is converted to int and is 1 i.e, true is 1 and
val remains the same.

"IF" argument evaluation order?

if(a && b)
{
do something;
}
is there any possibility to evaluate arguments from right to left(b -> a)?
if "yes", what influences the evaluation order?
(i'm using VS2008)
With C++ there are only a few operators that guarantee the evaluation order
operator && evaluates left operand first and if the value is logically false then it avoids evaluating the right operand. Typical use is for example if (x > 0 && k/x < limit) ... that avoids division by zero problems.
operator || evaluates left operand first and if the value is logically true then it avoids evaluating the right operand. For example if (overwrite_files || confirm("File existing, overwrite?")) ... will not ask confirmation when the flag overwrite_files is set.
operator , evaluates left operand first and then right operand anyway, returning the value of right operand. This operator is not used very often. Note that commas between parameters in a function call are not comma operators and the order of evaluation is not guaranteed.
The ternary operator x?y:z evaluates x first, and then depending on the logical value of the result evaluates either only y or only z.
For all other operators the order of evaluation is not specified.
The situation is actually worse because it's not that the order is not specified, but that there is not even an "order" for the expression at all, and for example in
std::cout << f() << g() << x(k(), h());
it's possible that functions will be called in the order h-g-k-x-f (this is a bit disturbing because the mental model of << operator conveys somehow the idea of sequentiality but in reality respects the sequence only in the order results are put on the stream and not in the order the results are computed).
Obviously the value dependencies in the expression may introduce some order guarantee; for example in the above expression it's guaranteed that both k() and h() will be called before x(...) because the return values from both are needed to call x (C++ is not lazy).
Note also that the guarantees for &&, || and , are valid only for predefined operators. If you overload those operators for your types they will be in that case like normal function calls and the order of evaluation of the operands will be unspecified.
Changes since C++17
C++17 introduced some extra ad-hoc specific guarantees about evaluation order (for example in the left-shift operator <<). For all the details see https://stackoverflow.com/a/38501596/320726
The evaluation order is specified by the standard and is left-to-right. The left-most expression will always be evaluated first with the && clause.
If you want b to be evaluated first:
if(b && a)
{
//do something
}
If both arguments are methods and you want both of them to be evaluated regardless of their result:
bool rb = b();
bool ra = a();
if ( ra && rb )
{
//do something
}
In this case, since you're using &&, a will always be evaluated first because the result is used to determine whether or not to short-circuit the expression.
If a returns false, then b is not allowed to evaluate at all.
Every value computation and side effect of the first (left) argument of the built-in logical AND operator && and the built-in logical OR operator || is sequenced before every value computation and side effect of the second (right) argument.
Read here for a more exhaustive explanation of the rules set:
order evaluation
It will evaluate from left to right and short-circuit the evaluation if it can (e.g. if a evaluates to false it won't evaluate b).
If you care about the order they are evaluated in you just need to specify them in the desired order of evaluation in your if statement.
The built-in && operator always evaluates its left operand first. For example:
if (a && b)
{
//block of code
}
If a is false, then b will not be evaluated.
If you want b to be evaluated first, and a only if b is true, simply write the expression the other way around:
if (b && a)
{
//block of code
}

Does gcc or other compilers auto convert bitwise or's to boolean or's when used in conditional expressions?

If I have a C statement with the logical OR operator || :
if (isFoo() || isBar())
blah();
I know the compiler generated code will not execute isBar() if isFoo() returns true.
What about the bitwise OR operator | ?
if (isFoo() | isBar())
blah();
Likely this is sloppy writing, or if the writer requires isBar() and isFoo() to be both be executed because of those functions' side-effects, then they should express their intent more clearly. Or maybe I'm wrong and this is an acceptable C/C++ idiom.
Nevertheless, will a decent compiler actually generate a temporary variable to do the bitwise or'ing of the return values of isFoo() and isBar() when optimizations are turned on? Or will it instead convert the bitwise OR operation into a logical OR operation in order to allow short-circuit'ing of the boolean expression in order to prevent the calling of isBar()?
The compiler is free to optimize the "or'ing" however it wants, but the program must behave as if both function calls actually happen, and they could happen in either order. This actually bit me once when I naively changed a || to | because I needed both calls to happen, but forgot that the right-hand call could happen before the left-hand one and that the right-hand one depended on the results of the left-hand one...and the bug didn't show up until somebody decided to try compiling my code with pcc instead of gcc. So my advice is to be careful with stuff like this and write out what you mean clearly.
Finally, note that I said "as if both function calls actually happen", because in the case where the compiler can determine that a function has no side effects, it might optimize out the right-hand side if the left-hand side resulted in a nonzero value.
"Nevertheless, will a decent compiler actually generate a temporary
variable to do the bitwise or'ing of the return values of isFoo() and
isBar() when optimizations are turned on?"
Yes. Short circuiting does not apply to bitwise operators.
No, this is not a reasonable coding practice. Apart from ||'s short-circuit and ordering semantics, it performs a different operation than |.
|| yields 1 if either operand is non-zero, 0 if both are zero.
| yields the bitwise or of its operands.
As it happens, the truth value of the result is going to be the same (I realized this as I was typing this answer). But consider the corresponding && vs. & operators. This:
if (isFoo() && isBar())
will be true if and only if both functions return a non-zero value, but this:
if (isFoo() & isBar())
will be true if and only if the bitwise and of the results is non-zero. If isFoo() returns 1 and isBar() returns 2 (both true results), then isFoo & isBar() will be 0, or false.
Note that the is*() functions declared in <ctype.h> are only specified to return non-zero for true; they can and do return values other than 0 or 1.
If you really want to avoid the short-circuit behavior of ||, assign the results to temporaries:
bool is_foo = isFoo();
bool is_bar = isBar();
if (is_foo && is_bar) ...
We are talking straight C here so we must have something like
typedef int BOOL;
BOOL isFoo();
BOOL isBAr();
This is because ony C++ (and not C) has a boolean type.
Now when we evaluate isFoo() || isBar() the compiler knows that since we are using logical or if isFoo() returns true, the the whole statement will evaluate to true regardless of the value of isBar(), the compiler can therefore safely short circuit `isBar().
However when we evaluate isFoo() | isBar() we are effectively ORing two integers. The compiler has no way of knowing that isFoo() and isBar() can only return 0 or 1 and therefore will have to evaluate both expressions because even if isFoo() returns 1, the final result may be something different (like 3).
C++ does have a bool type and if isFoo() and isBar() return bools the compiler really does not have to evalueate isBar(). I am not an expert on the C++ specification but I imagine since bitwise operators do not make sense for bool types, the bools will be promoted to int and evaluated accordingly.

Explanation for assert macro

I couldn't comment on the answer itself, so: about Using comma to prevent the need for brace pair
#define MY_ASSERT(expr) ((expr) || (debugbreak(), 0))
Here debugbreak() returns void, but we still wish to have 0 as an rvalue.
How does (debugbreak(), 0) work to return 0? I understand that the return value of debugbreak() is discarded and 0 is returned, but debugbreak generates an exception, so how can anything be evaluated afterward? I suppose my question can be generalised to any similar binary operator where the first part being evaluated exits the program.
It's a type system hack.
#define MY_ASSERT(expr) ((expr) || (debugbreak(), 0))
// note the or operator here ^
The || operator takes two bool-typed (or convertible) expressions. debugbreak() is void-typed. To make it bool, use the following rule:
(FOO, BAR)
// ^ determines the type of the entire comma expression
This is the same as {FOO; BAR} except that a block (in braces) has no type.
Nothing will be evaluated if the assert fires, but both expressions must have the right return type, otherwise this macro will just break compilation.
The basic idea is pretty simple. He's trying to get an effect pretty much the same as if he'd written: if (!expr) debugbreak();. For a macro, however, he wants that as a single expression. To do that, he's using ||, which evaluates its left argument, then if and only if that is false, evaluates the right argument -- then produces an overall result that is the logical OR of the two operands.
In this case, he doesn't really care about that logical OR that's produced as a result; he just wants the evaluate the left, then if it's false evaluate the right. The compiler, however does care -- in particular, it demands that both operands of || have some type that can be converted to bool (or, in C, 0 or 1).
To give the compiler that, he uses the comma operator, which evaluates its left operand, then its right operand and produces the value of the right operand as the result. That lets him get the debugbreak() evaluated, while the 0 keeps the compiler happy by giving it an int as the result value, which it can then OR with whatever value was produced by the expr to produce the result of the overall expression (which, of course, is irrelevant and almost certain to be ignored).
I think what your all missing is the fact that ( A || B ) follows short circuiting rules.
If A is true then there is NO NEED to evaluate B. Since B does not need to be evaluated DebugBreak() never gets called.
If A is false, then we HAVE to evaluate B to determine the output of ( A || B ). There is no short circuit. (DebugBreak(), 0) of more Appropriately (DebugBreak(), false)
http://www.student.cs.uwaterloo.ca/~cs132/Weekly/W02/SCBooleans.html
http://msdn.microsoft.com/en-us/library/zs06xbxh(VS.80).aspx