Does C always evalute all statements connected with && or || - c

pretty simple question I have here, but I couldn't find the answer:
Assume I have some conditional clause made up of several conditions. E.g. something like
if((a == b && strcmp(string1, string)) || x <= 5)
My question is: Will all of those statements be evaluated, no matter what the result of the first ones was, or will the evaluation stop once the result is clear.
As I am not sure whether my question is clear, here's an example:
if(a == 5 || b > 12 || (c = someFun()) == 3)
In this case, if a == 5, no further checks would be required, because the result of the big statement is TRUE, so we could simply continue. This would mean that someFun() would not be evaluated.
Is this the case? I know Java makes a difference here between && and & resp. || and | (the latter aren't available in C anyways), but I do not know how C handles this

These operators are short-circuiting in C (and C++).

C evaluates until it knows the answer, so:
EvalsToTrue() && EvalsToAnything() evaluates both
EvalsToFalse() && EvalsToAnything() evaluates only the first
EvalsToTrue() || EvalsToAnything() evaluates only the first
EvalsToFalse() || EvalsToAnything() evaluates both

The left-hand side expression is always evaluated. The right-hand side expression is evaluated as follows:
a || b -- b will be evaluated only if a evaluates to false
a && b -- b will be evaluated only if a evaluates to true
&& has higher precedence than ||, thus
a || b && c -- b && c will be evaluated only if a evaluates to false
a && b || c -- c will be evaluated only if a && b evaluates to false
(a || b) && c -- c will be evaluated only if a || b evaluates to true
a && (b || c) -- b || c will be evaluated only if a evaluates to true
a && b && c -- c will be evaluated only if a && b evaluate to true
a || b || c -- c will be evaluated only if a || b evaluate to false

Evaluation starts at left most.. and exits when the overall condition is no longer valid..

Related

Order of checking the conditions in C

So I was reading about the order of different operators, and I read that && has higher importance than || and it would evaluate sooner (source). Then somebody asked a question about what this piece of code would print:
#include <stdio.h>
int main(){
int a=0, b=0, c=0, d=0;
if(a++>0 || ++b==1 || c--<=0 && d++>c--){
printf("if\na:%d\nb:%d\nc:%d\nd:%d\n",a,b,c,d);
}
else{
printf("else\na:%d\nb:%d\nc:%d\nd:%d\n",a,b,c,d);
}
return 0;
}
And I thought that the c-- <= 0 && d++ > c-- would evaluate first, which is true in total. after the process, c would be equal to -2 and d would be equal to 1. Then it would start checking from the left side, evaluating a++ > 0 || ++b == 1 which is true, a would be 1 at the end and b is 1 in the condition and after that. so the total condition would be true || true and it is true, so we will print:
if
a:1
b:1
c:-2
d:1
Yes? Apparently, no. I've tested it with GCC (Mingw) on my system (Windows 10), and with an online compiler (this one) and both printed:
if
a:1
b:1
c:0
d:0
I've changed the condition into this: if(a++>0 || ++b==1 || (c--<=0 && d++>c--) ) but the output is the exact same thing on both places. Is there something that I don't pay attention to? Or is this something like a bug? It almost looks like that || and && have the same priority and the whole thing is evaluated from the left side, and short-circuits occurs and other things. If I change the ++b==1 part into ++b==0, then the output is the same as I predicted.
Thanks in advance for any kind of help :)
The expression in this question:
if(a++>0 || ++b==1 || c--<=0 && d++>c--)
is a classic example of a horrible, horrible expression, outrageously unrealistic and impractical, and punishingly difficult to understand, which nevertheless does a good job of illustrating a super important point: precedence is not the same as order of evaluation.
What precedence really tells us is how the operators are hooked up with their operands. So given the simplified expression
A || B || C && D
which two subexpressions do the first ||, and the second ||, and the && actually tie together and operate on? If you're a compiler writer, you answer these questions by constructing a "parse tree" which explicitly shows which subexpression(s) go with which operators.
So, given the expression A || B || C && D, does the parse tree for the expression look like this:
&&
/ \
|| D
/ \
|| C
/ \
A B
or like this:
||
/ \
A ||
/ \
B &&
/ \
C D
or like this:
||
/ \
/ \
|| &&
/ \ / \
A B C D
To answer this, we need to know not only that the precedence of && is higher than ||, but also that || is left-associative. Given these facts, the expression
A || B || C && D
is parsed as if it had been written
(A || B) || (C && D)
and, therefore, results in the third of the three candidate parse trees I showed:
||
/ \
/ \
|| &&
/ \ / \
A B C D
But now we're in a position to really see how the "short circuiting" behavior of the || and && operators is going to be applied. That "top" || is going to evaluate its left-hand side and then, if it's false, also evaluate the right-hand side. Similarly, the lower || is going to evaluate its left-hand side. So, no matter what, A is going to get evaluated first. For the expression in the original question, that corresponds to a++ > 0.
Now, a++>0 is false, so we're going to have to evaluate B, which is ++b == 1. Now, that is true, so the result of the first || is "true".
So the result of the second (top) || operator is also "true".
So the right-hand side of the top || operator does not have to be evaluated at all.
So the entire subexpression containing && will not be evaluated at all.
So even though && had the highest precedence, it ended up getting considered last, and (since the stuff to the left involved || and was true) it did not end up getting evaluated at all.
The bottom line, as I started out by saying, is that precedence does not determine order of evaluation.
Also, if it wasn't said elsewhere, this guaranteed, left-to-right behavior is only guaranteed for the || and && operators (and, in a different way, for the ternary ?: operator). If the expression had been
A + B + C * D
it would not have been true that, as I said earlier, "no matter what, A is going to get evaluated first". For arithmetic operators like + and *, there's no way to know whether the left-hand side or the right-hand side is going to get evaluated first.

Assignment operators in if statement

int a = 0, b = 0, c = -1;
if (b = a || b == ++c )
a+=3;
Why are the values of a,b and c 3 , 1, 0 respectively? More specifically, why is b 1 and not 0?
Because || has higher precedence than =, so it's being parsed as if you'd written.
if (b = (a || (b == ++c)))
This calculates a || (b == ++c). This is true because b == 0 and ++c == 0, so b == ++c is true, and true is 1.
Add parentheses to get what you want:
if ((b = a) || (b == ++c))
But IMHO it's generally best to avoid writing such complex expressions. Do them as separate statements:
b = a;
if (b || b == ++c)
Once you are clear with the precedence of operators,it will be easy for you to tackle such type of questions.Go through this to know about operator precedence in C.
You should see my answer after going through the precedence list because then it will get more easily inside your mind.
Now,coming to your question....
Out of all the operators used in the above code, ++c has the highest precedence.So the value of c becomes 0 and then value of c is compared to value of b here b == ++c which evaluates to true i.e 1 and now || of 1 and a is taken which is 1.
And finally this result 1 is assigned to b.So the overall execution of if statement evaluates to true and value of a is incremented by 3.
Hence finally the value of a=3,b=1 and c=0.

Short circuit evaluation with both && || operator

I know what is short circuit evaluation in C.
a && b (operand b is not checked if a = 0)
a || b (operand b is not checked if a = non zero)
But I am stuck at this question
int x = 0;
if (5 || 2 && ++x)
printf("%d", x);
This outputs 0.
My first thinking goes as follows:
According to precedence table , precedence is ++, &&, || (descending order)
++x: evaluated.x becomes 1.
2 && ++x evaluated. Both operands are evaluated.
|| is evaluated.
But according to this, 1 should be printed, not 0.
My second thinking goes as this:
5 || anything
anything is not evaluated because of short circuit evaluation, so no precedence comes into play here.
The expression 5 || 2 && ++x is equivalent to 5 || (2 && ++x) due to operator precedence.
The run time evaluates the expression 5 || 2 && ++x from left to right.
As we know in OR if first condition is true it will not check the second condition.
So here 5 evaluated as true and so (2 && ++x) will not be performed.
That's why x will remain 0 here.
Correct. The expression is short circuited. You can test it with this.
if(5 || ++x) {
printf("%d\n",x);
}

inner short circuit evaluation in c

I know that Java and C/C++ have short circuit evaluation, i.e., in if (a && b), b will never evaluated if a is not true.
But what if I have expression like if ( (a && b) OP c ) (where OP is an arbitrary logical operator), will b evaluated if a = false? Thanks.
C Standards say that -
6.5.13 Logical AND operator
The && operator guarantees left-to-right evaluation......
.If the first operand compares equal to 0, the second operand is not evaluated.
So in case a==flase b will not be evaluated.
You will always have if a = false : a && b == 0 whatever the value of b. Why would an operation done after the evaluation will change that ?
a b | a && b
0 0 | 0
0 1 | 0
If a=false then condition for b will not be checked so (a && b) is ALWAYS false
and the next condition depends upon the OP used if it is && it will not be evaluated. If it is || it will be evaluated.
So
((a && b) OP c)
here if a=false (a && b) will be always false.

Why c is not incremented in the output?

I was working on the Basics of C and was trying to solve the problem below could any one explain why the output of variable c is different?
What is the output of the following program?
int main()
{
int a = -3, b = 2, c= 0, d;
d = ++a && ++b || ++c;
printf ("a = %d, b = %d, c = %d, d = %d", a, b, c, d);
}
Ans: -2, 3, 0, 1
Why c is not incremented in the output ?
The variable c is not incremented because the RHS (right-hand side) of an || is not executed unless the LHS evaluates to false, and the LHS evaluates to true. The C || and && operators are 'short-circuit' operators; they do not evaluate the second operand unless the first is insufficient to determine the overall truth of the expression.
The && binds tighter than the ||, so the operation can be parenthesized as:
d = (++a && ++b) || ++c;
The value of ++a is -2, which evaluates to true (because any value that is not 0 evaluates to true); the value of ++b is 3, which evaluates to true; so the value of the && term is true. Because true || false and true || true both evaluate to true, there is no need to evaluate the RHS to know the overall result. (The analogous rule for && is that if the first term evaluates to false, there is no need to evaluate the second because the overall expression must be false. If you had a = -1; before the test, then b would not be incremented, because ++a would be zero or false, so the RHS of the && is unevaluated. Of course, then c would be incremented because the LHS of the || would be false, and the RHS would have to be evaluated to determine the overall result.)
Because ++a && ++b evaluates to true.
It's called short-circuiting. Expressions inside conditions are evaluated from left-to-right. If your case, if the first condition in the OR clause is evaluated to true, there's no point for the second one to also be evaluated, since the whole expression is known to be true already.
In C, the boolean logic operators && and || are short-circuiting. This means that they only evaluate their right side, if evaluating the left side is not enough to know the answer.
For your code, this has the effect of never evaluating ++c, since the left-hand side is not zero and thus the boolean or's result will be true, and there's no need to do more work.
It is lazy boolean expressions evaluation.
The execution is:
++a gives -2
++b gives 3
-2 && 3 gives 1
Okay! No need to check result of ||. So ++c is not evaluated.
The rule is: expression part X is not evaluated in cases: (0 && X), (1 || X). Here 1 is "not 0" of course.
d= ++a && ++b || ++c
d= ++(-2) && ++b || ++c
d= -1 && ++b || ++c
d= true && ++b || ++c
d= true && ++2 || ++c
d= true && true || ++c
d= true || ++c
d= 1
That's roughly how it works behind the scene...

Resources