In C does the logical operator end if one side of a || is true? [duplicate] - c

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) )

Related

How this logical operator works? [duplicate]

This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 1 year ago.
#include<stdio.h>
int main()
{
int a=-10,b=3,c=0,d;
d= a++||++b &&c++;
printf("%d %d %d %d ",a,b,c,d);
}
How above expression is evaluates. I have read preceedence but still i am getting confused. Kindly give me the right solution of this in step by step.
In case of || and && operators the order of evaluation is indeed defined as left-to-right.So, operator precedence rules tell you that the grouping should be
(a++) || ((++b) && (c++))
Now, order-of-evaluation rules tell you that first we evaluate a++, then (if necessary) we evaluate ++b, then (if necessary) we evaluate c++, then we evaluate && and finally we evaluate ||.
I have a feeling this is a homework question, so I'll try to give extra explanation. There are actually a lot of concepts going on here!
Here are the main concepts:
Pre- and post- increment and decrement. ++a increments a before the value is used in an expression, while a++ increments a after the value is used in the expression.
Operator precedence. Specifically, && has higher precedence than ||, which means that the assignment of d should be should be read as d = (a++) || (++b && c++);
Expression evaluation order. The link shows a whole list of evaluation rules for C. In particular, item 2 says (paraphrasing) that for operators || and &&, the entire left side is always fully evaluated before any evaluation of the right-hand side begins. This is important because of...
Short-circuit boolean evaluation, which says that, for operators && and ||, if the value of the left-hand term is enough to determine the result of the expression, then the right-hand term is not evaluated at all.
Behaviour of boolean operators in C. There is no inbuilt boolean type in C, and operators && and || work on integer values. In short, an argument is 'true' if it is nonzero, and false if it equals zero. The return value is 1 for true and 0 for false.
Putting this all together, here is what happens:
After the first line, a is -10, b is 3, c is 0 and d is unset.
Next, the variable d needs to be assigned. To determine the value assigned to d, the left hand term of (a++) || (++b && c++) is evaluated, which is a++. The value USED in the expression is 10, however the value of a after this expression is -9 due to the post-increment.
For the purposes of the boolean operator, the value 10 is true, and therefore value of the || expression is 1. Because of short-circuit evaluation, this means that ++b && c++ is not evaluated at all, so the increments do not happen. Thus we have d = 1.
At the end, the values are: a = -9, b = 3, c = 0, d = 1.
So the program prints out -9 3 0 1.

"And" and "Or" operators in conditionals in C [duplicate]

This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 6 years ago.
I always wondered about something and couldn`t find an answer somewhere else. If I have this piece of code:
if ((cond1) &&(cond2) && (cond 3) && (cond 4))
{
// do something
}
Let`s say the first condition is false, then my program will verify the other conditions too, or just skip verifying them?
But if I have
if ((cond1) ||(cond2) || (cond 3) || (cond 4))
{
// do something
}
and cond 1 is true, will my program go instantly on the if part or continue to verify the other conditions too?
Quoting C11 standard, chapter §6.5.13, Logical AND operator (emphasis mine)
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.
So, if the first condition (LHS operand) evaluates to false, the later conditions, i.e., RHS operand of the && is not evaluated.
Similarly (Ironically, rather), for Logical "OR" operator,
Unlike the bitwise | 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 unequal to 0, the second operand is
not evaluated.
In C both && and || "sort-circuit", meaning if evaluation of the left operand is enough to determine the outcome then the right operand is not evaluated.

Why do logical operators in C not evaluate the entire expression when it's not necessary to?

I was reading my textbook for my computer architecture class and I came across this statement.
A second important distinction between the logical operators '&&' and '||' versus their bit-level counterparts '&' and '|' is that the logical operators do not evaluate their second argument if the result of the expression can be determined by evaluating the first argument. Thus, for example, the expression a && 5/a will never cause a division by zero, and the expression p && *p++ will never cause the dereferencing of a null pointer. (Computer Systems: A Programmer's Perspective by Bryant and O'Hallaron, 3rd Edition, p. 57)
My question is why do logical operators in C behave like that? Using the author's example of a && 5/a, wouldn't C need to evaluate the whole expression because && requires both predicates to be true? Without loss of generality, my same question applies to his second example.
Short-circuiting is a performance enhancement that happens to be useful for other purposes.
You say "wouldn't C need to evaluate the whole expression because && requires both predicates to be true?" But think about it. If the left hand side of the && is false, does it matter what the right hand side evaluates to? false && true or false && false, the result is the same: false.
So when the left hand side of an && is determined to be false, or the left hand side of a || is determined to be true, the value on the right doesn't matter, and can be skipped. This makes the code faster by removing the need to evaluate a potentially expensive second test. Imagine if the right-hand side called a function that scanned a whole file for a given string? Wouldn't you want that test skipped if the first test meant you already knew the combined answer?
C decided to go beyond guaranteeing short-circuiting to guaranteeing order of evaluation because it means safety tests like the one you provide are possible. As long as the tests are idempotent, or the side-effects are intended to occur only when not short-circuited, this feature is desirable.
A typical example is a null-pointer check:
if(ptr != NULL && ptr->value) {
....
}
Without short-circuit-evaluation, this would cause an error when the null-pointer is dereferenced.
The program first checks the left part ptr != NULL. If this evaluates to false, it does not have to evaluate the second part, because it is already clear that the result will be false.
In the expression X && Y, if X is evaluated to false, then we know that X && Y will always be false, whatever is the value of Y. Therefore, there is no need to evaluate Y.
This trick is used in your example to avoid a division by 0. If a is evaluated to false (i.e. a == 0), then we do not evaluate 5/a.
It can also save a lot of time. For instance, when evaluating f() && g(), if the call to g() is expensive and if f() returns false, not evaluating g() is a nice feature.
wouldn't C need to evaluate the whole expression because && requires both predicates to be true?
Answer: No. Why work more when the answer is known "already"?
As per the definition of the logical AND operator, quoting C11, chapter §6.5.14
The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it
yields 0.
Following that analogy, for an expression of the form a && b, in case a evaluates to FALSE, irrespective of the evaluated result of b, the result will be FALSE. No need to waste machine cycle checking the b and then returning FALSE, anyway.
Same goes for logical OR operator, too, in case the first argument evaluates to TRUE, the return value condition is already found, and no need to evaluate the second argument.
It's just the rule and is extremely useful. Perhaps that's why it's the rule. It means we can write clearer code. An alternative - using if statements would produce much more verbose code since you can't use if statements directly within expressions.
You already give one example. Another is something like if (a && b / a) to prevent integer division by zero, the behaviour of which is undefined in C. That's what the author is guarding themselves from in writing a && 5/a.
Very occasionally if you do always need both arguments evaluated (perhaps they call functions with side effects), you can always use & and |.

Conditional execution based on short-circuit logical operation

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.

Order of logical OR execution in C

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.

Resources