inner short circuit evaluation in c - 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.

Related

how will this expression will evaluate in C?

I can't figure out how will this expression be evaluated in C?
I'm a bit confused with the evaluation of an expression inside printf?
If an expression inside printf evaluates from right to left then the evaluation of expression should've stopped after encountering (c>10), but it printed '1' to the output screen?
This is not exact syntax of C, but a question that was asked to me.
integer a = 50, b = 25, c = 0;
printf( a > 45 || b > 50 && c > 10 );
This expression
a > 45 || b > 50 && c > 10
is equivalent to expression
( a > 45 ) || ( b > 50 && c > 10 )
Thus if this subexpression ( a > 45 ) evaluates to true then the second subexpression will not evaluate and the result is equal 1 (of type int).
Otherwise this sub expression
( b > 50 && c > 10 )
is equivalent to
( b > 50 ) && ( c > 10 )
if ( b > 50 ) evaluates to false then the whole result is false (0 in C) and the second subexpression will not evaluate. Otherwise the result is the value of
the subexpression c > 10. If c > 10 then the result is an object of type int with value 1 or if not ( c > 10 ) then the value of the result is 0.
If the variables have values as it is shown in your question
int a = 50, b = 25, c = 0;
then the first subexpression
a > 45
evaluates to true and the result is 1 of type int. The second subexpression
b > 50 && c > 10
will not even evaluate.
Consider the following demonstrative program
#include <stdio.h>
int f( int x )
{
printf( "f is called for %d\n", x );
return x;
}
int main( void )
{
int a = 50, b = 25, c = 0;
f( f( a ) > 45 || f( b ) > 50 && f( c ) > 10 );
return 0;
}
Its output is
f is called for 50
f is called for 1
As you can see it was enough to calculate the expression f( a ) > 45 to get the result equal to 1.
It would be undefined behaviour. The first argument to printf must be a format string. Most likely it will crash. What saves you is that "integer" is not a type, so it's not going to compile.
Both the || and && operators force left-to-right evaluation. The left-hand operand will be fully evaluated (and all side effects applied) before the right-hand operand is evaluated.
Furthermore, both operators short-circuit - depending on the value of the left-hand operand, the right-hand operand may not be evaluated at all.
For
a || b
if a is true, then the entire expression is true regardless of the value of b, so b isn't evaluated.
Similarly, for
a && b
if a is false, then the entire expression is false regardless of the value of b, so b isn't evaluated.
&& has higher precedence than ||, so
a || b && c
will be parsed as
a || (b && c)
and
a && b || c
will be parsed as
(a && b) || c
So...
a > 45 || b > 50 && c > 10
is parsed as
a > 45 || (b > 50 && c > 10 )
Since a == 50, a > 45 is true. Since a > 45 is the left-hand operand of the || operator, the whole expression is true regardless of the right-hand operand, so b > 50 && c > 10 isn't evaluated at all.
The result of expression is 1 (true).
Unfortunately, printf expects its first argument to point to a character string (the format string), and 1 is most likely not a valid address on your platform, so the result of this code will most likely be a segfault. The easy fix would be to write
printf( "%d\n", a > 45 || b > 50 && c > 10 );
The context in which an expression appears affects whether it is evaluated, but not how. The order in which subexpressions of a larger expression are evaluated is controlled by operator precedence and associativity.
Among the operators in your expression, > has greatest precedence, then &&, then ||. All associate from left to right. Therefore, your expression is evaluated exactly the same as if it were written like so:
(a > 45) || ((b > 50) && (c > 10))
Furthermore, the && and || operators perform short-circuit evaluation. This seems to be a point of confusion for you. Short-circuit evaluation means that if the result of an && or || operation is determined by the value of the left-hand operand, then the right-hand operand of that operation is not evaluated. That does not affect whether or how other operations are evaluated, except to the extent that the result of the short-circuited operation is used as an operand.
In this case, however, because || associates left-to-right, a > 45 is evaluated first, producing 1 (true). Because this determines the result of the || operation, its right-hand operand is not evaluated. Relative operator precedence yields the right-hand operand being the remainder of the overall expression, as shown above, so none of that will be evaluated. Even if it were evaluated, however, the result of the overall expression would still be 1, because the left-hand operand evaluates to 1, regardless of the right-hand sub-expression. That's why the right-hand side of the || does not need to be evaluated.

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.

Basic programming exercise about logical operators

I have a problem with a question in my book:
#include<stdio.h>
void main()
{
int a=5, b=-7, c=0, d;
d = ++a && ++b || ++c;
printf("\n%d%d%d%d",a,b,c,d);
}
The question asks me what is the output of the code. I ran it and the result on the screen is 6-601. I understand why a=6 and b=-6, but I don't understand why c=0 and d=1?
I believe you already got your answer, but just to elaborate a bit step-by-step, let me add one more clarification here. Firstly, to quote the properties of the && and || operators, from C11 standard, chapter §6.5.13 and §6.5.13, respectively,
(I)
The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it
yields 0. [...] If the first operand compares equal to 0, the second
operand is not evaluated.
and
(II)
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. [...]. If the first operand compares unequal to 0, the second operand is
not evaluated.
and they both guarantee left-to-right evaluation. So, comparing your code,
d = ++a && ++b || ++c;
it happens like
d = ((++a && ++b) || ++c );
which evaluates to
d = (( 6 && ++b ) || ++c);
and then
d = ( ( 6 && (-6) ) || ++c);
Now in above stage, (I) is fulfilled and it comes down to
d = ( 1 || ++c);
Now, following the emphasis, which already meets the (II), so no further evaluation of the RHS operand of || is performed (i.e., ++c is not evaluated), and it appears to be d = 1 and the final result, 1, is stored into d.
That's how, a == 6, b == -6, c == 0 and d ==1.
Having said that, void main() should be changed to int main(void), at least to conform with the standard.
The || OR operator is short-circuiting, which means that if the left side is true then the right side is not evaluated. In this case ++a && ++b evaluates to true, so ++c is never run and c keeps its value of zero.
Also since it evaluates to true, this is denoted with 1 which is stored in d.
Any non-zero value is considered to be true and the result of boolean operations is defined to be 0 or 1 as an integer.

How to determine if logical expressions are equivalent or not

I do not know how to test this using a truth table because I haven't been taught that yet. Can someone explain if the expression !(a < b) the same as !a >= !b ?
Expression (a < b) is logical expression. We can say about it that it is true or it is false. (a < b) is true for example when a = 1 and b = 3. Otherwise, (a < b) is false when a = b or for example, when a = 5 and b = 2.
!(expression) -- is unary logical operator NOT which is true when expression is false, and it is false when expression is true.
So, when you write !(a < b) logically it means NOT (a < b), so it is (a >= b).
In C you can use unary operator !. The result of the logical negation operator ! is 1 if the value of its operand is zero, and 0 if the value of its operand is nonzero. The type of the result is int. The logical negation operator is applicable to any arithmetic type and to pointers.
So, technically, syntax of expression (!a >= !b) is correct, but from logical point of view its nonsense in your case.

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

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

Resources