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
Related
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
}
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
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Safety concerns about short circuit evaluation
What does the standard say about evaluating && expressions - does it guarantee that evaluation of parameters will stop at the first false?
E.g.:
Foo* p;
//....
if ( p && p->f() )
{
//do something
}
is the f() guaranteed not to be called if p == NULL?
Also, is the order of evaluation guaranteed to be the order of appearence in the clause?
Might the optimizer change something like:
int x;
Foo* p;
//...
if ( p->doSomethingReallyExpensive() && x == 3 )
{
//....
}
to a form where it evaluates x==3 first? Or will it always execute the really expensive function first?
I know that on most compilers (probably all) evaluation stops after the first false is encountered, but what does the standard say about it?
What does the standard say about evaluating && expressions - does it guarantee that evaluation of parameters will stop at the first false?
Yes. That is called short-circuiting.
Also, is the order of evaluation guaranteed to be the order of appearence in the clause?
Yes. From left to right. The operand before which the expression short-circuited doesn't get evaluated.
int a = 0;
int b = 10;
if ( a != 0 && (b=100)) {}
cout << b << endl; //prints 10, not 100
In fact, the above two points are the keypoint in my solution here:
Find maximum of three number in C without using conditional statement and ternary operator
In the ANSI C standard 3.3.13:
Unlike the bitwise binary & operator, the && operator guarantees
left-to-right evaluation; there is a sequence point after the
evaluation of the first operand. If the first operand compares equal
to 0, the second operand is not evaluated.
There is an equivalent statement in the C++ standard
&& (and ||) establish sequence points. So the expression on the left-hand side will get evaluated before the right-hand side. Also, yes, if the left-hand side is false/true (for &&/||), the right-hand side is not evaluated.
What does the standard say about evaluating && expressions - does it guarantee that evaluation of parameters will stop at the first false?
Also, is the order of evaluation guaranteed to be the order of appearence in the clause?
5.14/1. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
This only works for the standard && operator, user defined overloads of operator && don't have this guarantee, they behave like regular function call semantics.
Might the optimizer change something like:
if ( p->doSomethingReallyExpensive() && x == 3 )
to a form where it evaluates x==3 first?
An optimizer may decide to evaluate x == 3 first since it is an expression with no side-effects associated if x is not modified by p->doSomethingReallyExpensive(), or even evaluate it after p->doSomethingReallyExpensive() already returned false. However, the visible behavior is guaranteed to be the previously specified: Left to right evaluation and short-circuit. That means that while x == 3 may be evaluated first and return false the implementation still has to evaluate p->doSomethingReallyExpensive().
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.
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?