As the evaluation of logical operators && and || are defined as "short circuit", I am assuming the following two pieces of code are equivalent:
p = c || do_something();
and
if (c) {
p = true;
}
else {
p = do_something();
}
given p and c are bool, and do_something() is a function returning bool and possibly having side effects. According to the C standard, can one rely on the assumption the snippets are equivalent? In particular, having the first snippet, is it promised that if c is true, the function won't be executed, and no side effects of it will take place?
After some search I will answer my question myself referencing the standard:
The C99 standard, section 6.5.14 Logical OR operator is stating:
Unlike the bitwise | 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 unequal
to 0, the second operand is not evaluated.
And a similar section about &&.
So the answer is yes, the code can be safely considered equivalent.
Yes, you are correct in your thinking. c || do_something() will short-circuit if c is true, and so will never call do_something().
However, if c is false, then do_something() will be called and its result will be the new value of p.
Related
This question already has answers here:
Evaluation of C expression
(8 answers)
Closed 7 years ago.
I have been coding from a long time though I'm still a student programmer/ I'm usually good at programming but when questions like the one below are asked I get stuck. What will be the output and why of the following program?
int main()
{
int i=4,j=-1,k=0,w,x,y,z;
w=i||j||k;
print("%d",w);
return 0;
}
output:
1
why this result? what does the statement w=||j||k; means?
i || j || k is evaluated from left to right. It does that:
i == 4, which is true, so ORing it with any other value will yield true. That's it1.
The rest of the statement is not evaluated because || and && are short-circuit operators, that is, if in your statement i != 0, neither j nor k will be evaluated because the result is guaranteed to be 1. && works similarly.
That's important to remember if you have something like f() || k(), where k has some side effect like an output to screen or a variable assignment; it might not be executed at all.
The bitwise OR operator | really ORs the bitwise representations of the values instead; it evaluates all its operands.
1 Thanks to #SouravGosh on that!
In your code,
w=i||j||k;
is equivalent to
w= ((i||j) || k);
That means, first the (i||j) will be evaluated, and based on the result (if 0), the later part will be evaluated.
So, in your case, i being 4, (i||j) evaluates to 1 and based on the logical OR operator semantics, the later part is not evaluated and the whole expression yields 1 which is finally assigned to w.
Related quotes, from C11 standard, chapter §6.5.14, Logical OR operator
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
then, regarding the evaluation of arguments,
[...] If the first operand compares unequal to 0, the second operand is
not evaluated.
and regarding the grouping,
[...] the || operator guarantees left-to-right evaluation;
The result of boolean operators yields an int value of 0 or 1.
See 6.5.13 and 6.5.14, paragraph 3.
The [...] operator shall yield 1 [or] 0. The result has type int.
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 9 years ago.
In C have the following:
return (abc(1) || abc(2));
If abc(1 == 1) returns true will then call abc(2)?
No, it won't. This is called "short-circuiting" and it is a common flow-control mechanism:
With a && b, b is only evaluated if a is true; if a is false, the whole expression must necessarily be false.
With a || b, b is only evaluated if a is false; if a is false, the whole expression may still be true.
No. It's guaranteed (by The Standard), that if abc(1) returns true, abc(2) will NOT be called.
If abc(1) returns false, that it's guaranteed, that abc(2) WILL be called.
It's similar with &&: if you have abc(1) && abc(2), abc(2) will be called ONLY IF abc(1) return true and will NOT be called, if abc(1) return false.
The idea behind this is:
true OR whatever -> true
false OR whatever -> whatever
false AND whatever -> false
true AND whatever -> whatever
This comes from the boolean algebra
If abc(1==1) returns true will then call abc(2) ?
No, it won't. This behavior is known as short-circuiting. It is guaranteed by C and C++ standards.
C11(n1570), § 6.5.13 Logical AND operator
Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; if the second operand is evaluated, there is a sequence point between the evaluations of
the first and second operands. If the first operand compares equal to 0, the second operand is not evaluated.
(Emphasis is mine.)
The same applies to the || operator.
abc(2) will be called only if abc(1) is false
According to C99 specification, logical OR operator says
The || operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If the first operand compares unequal to 0, the second operand is not evaluated.
|| (logical comparison) breaks further checking, while | (bitwise comparison) doesn't.
You might also read: Difference between | and || or & and && for comparison
nop, the second abc(2) is called only if the left statement is false
In C, the logical || operator is tested from left-to-right, guaranteed. For the whole statement to be true, either condition can be true. So || keeps going from left to right until one condition is true, and then stops (or it gets to the end). So no, if abc(1) returns true then abc(2) will not be called.
Contrast with &&, which keeps going from left to right until one condition is false (or it gets to the end).
No. This is actually non trivial and defined in standard that logical operators are evaluated from left to right. Evaluation is stopped when the value can be determined with out further evaluation of operands. At least I am 100% sure for AND and OR.
This is non trivial problem, because therefore the evaluation of operands cannot be implicitly parallelized or optimized by reorganization of order, as the expected outcome could differ.
E.g. run-time troubles in wide-use cases such as if (*ptr && (ptr->number > other_number) )
Was wondering if the next statement could lead to a protection fault and other horrible stuff if value of next is NULL(node being a linked list).
if (!node->next || node->next->some_field != some_value) {
Im assuming the second part of the OR is not evaluated once the first part is true. Am I wrong in assuming this? Is this compiler specific?
In the ISO-IEC-9899-1999 Standard (C99), Section 6.5.14:
The || operator shall yield 1 if either of its operands compare unequal
to 0; otherwise, it yields 0. The result has type int. 4 Unlike the
bitwise | 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 unequal to 0, the second operand is not
evaluated.
This is not compiler-specific. If node->next is NULL, then the rest of the condition is never evaluated.
In an OR,
if ( expr_1 || expr_2)
expr_2 only gets 'tested' when expr_1 fails (is false)
In an AND
if( expr_1 && expr_2 )
expr_2 only gets 'tested' when expr_1 succeeds (is true)
It is safe to assume that the right side boolean expression will not be evaluated if the left side evaluates to true. See relevant question.
It's not compiler specific. You can safely rely on short-circuiting and your code will work as expected.
You are correct.
It is compiler independent and always the first condition before OR operator(!node->next) is evaluated before evaluating the second condition(node->next->some_field != some_value) after OR operator. If the first condition is true, the entire expression just evaluates to true without evaluating the second condition.
You are just making the best use of this feature for your linked list. You are going further to access next pointer only if it is not NULL.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is short-circuiting boolean operators mandated in C/C++? And evaluation order?
AFAIK Short circuit evaluation means that a boolean expression is evaluated only up to the point that we can guarantee its outcome.
This is a common idiom in perl where we can write things like:
(is_ok() returns non-zero value on "OK")
is_ok() || die "It's not OK!!\n";
instead of
if ( ! is_ok() ) {
die "It's not OK!!\n";
}
This only works because the order of evaluation is always left-to right and that guarantees that the rightmost statement is only executed if the first statement if not "false".
In C I can do something simillar like:
struct foo {
int some_flag;
} *ptr = 0;
/* do some work that may change value of ptr */
if ( 0!=ptr && ptr->some_flag ) {
/* do something */
}
Is it safe to use this kind of idiom?
Or is there any chance that the compiler may generate code that evaluates ptr->some_flag before making sure that ptr is not a zero pointer? (I am assuming that if it is non-null it points to some valid memory region).
This syntax is convenient to use because it saves typing without losing readability (in my opinion anyway). However I'm not sure if it is entirely safe which is why I'd like to learn more on this.
NB: If the compiler has an effect on this, I'm using gcc 4.x
The evaluation order of short-circuit operators (|| and &&) is guaranteed by the standard to be left to right (otherwise they would lose part of their usefulness).
§6.5.13 ¶4
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.
§6.5.14 ¶4
Unlike the bitwise | 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
unequal to 0, the second operand is not evaluated.
Or is there any chance that the compiler may generate code that
evaluates ptr->some_flag before making sure that ptr is not a zero
pointer?
No, zero-chance. It is guaranteed by the standard that ptr->some_flag will not be evaluated if the first operand is false.
6.5.13-4
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.
/* do some work that may change value of ptr */
if ( 0!=ptr && ptr->some_flag ) {
/* do something */
}
Is it safe to use this kind of idiom?
Yes.
It is safe in the above example, however anyone maintaining such code may not realise that there is a dependency on the order of evaluation and cause an interesting bug.
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 5 years ago.
OK, I'm a little embarassed to ask this question, but I just want to be sure...
It is known that C uses short circuit evaluation in boolean expressions:
int c = 0;
if (c && func(c)) { /* whatever... */ }
In that example func(c) is not called because c evaluates to 0. But how about more sophisticated example where side effects of comparison would change the variable being compared next? Like this:
int c; /* this is not even initialized... */
if (canInitWithSomeValue(&c) && c == SOMETHING) { /*...*/ }
Function canInitWithSomeValue returns true and changes value at given pointer in case of success. Is it guaranteed that subsequent comparisons (c == SOMETHING in this example) uses value set by canInitWithSomeValue(&c)?
No matter how heavy optimizations the compiler uses?
Is it guaranteed that subsequent comparisons (c == SOMETHING in this example) uses value set by canInitWithSomeValue(&c)?
Yes. Because there is a sequence point
Between evaluation of the left and right operands of the && (logical AND), || (logical OR), and comma operators. For example, in the expression *p++ != 0 && *q++ != 0, all side effects of the sub-expression *p++ != 0 are completed before any attempt to access q.
A sequence point defines any point in a computer program's execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.
Yes. Because both && and || operator are also something called sequence points. The latter define when the side-effects of a previous operation should be complete and those of the next should not have begun.
Evaluation within the if statement composite condition is strictly left to right. The only circumstance under which the second test in your if would be optimized out is if the compiler can determine with 100% certainty that the first is identically equal to false.