Basic programming exercise about logical operators - c

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.

Related

Logical AND OR and increment precedence [duplicate]

This question already has answers here:
What is short-circuit evaluation in C?
(3 answers)
Closed 2 years ago.
I want to ask a question about the code below.
int a=1, b=3, c=1;
if((a||c--)&&(c&&b--)) printf("%d",b);
printf("%d %d %d",a,b,c);
Why does the code prints "21 2 1" rather than "1 2 0" ?
Thanks for your help.
Since the or is evaluated to true immediately in (a||c--), the c-- is never evaluated. The compiler does this. If a statement is true right off the bat, it won't bother evaluating the rest. So, c is never decremented as the right side of the or is never evaluated.
Both || and && force left-to-right evaluation - the LHS is evaluated first and all side effects applied, then based on the result the RHS is evaluated.
Both operators short-circuit:
for a || b, if a is non-zero, then the result of the expression is 1 regardless of the value of b, so b is not evaluated;
for a && b, if a is zero, then the result of the expression is 0 regardless of the value of b, so b is not evaluated.
&& has higher precedence than ||, so a || b && c is parsed as a || (b && c).
Putting all that together, (a||c--)&&(c&&b--) is evaluated as follows:
a || c-- is evaluated as follows:
a is evaluated - its result is 1, so
c-- is not evaluated; because of this c's value is not changed, and
the result of the expression is 1
c && b-- is evaluated as follows:
c is evaluated - its result is 1, so
b-- is evaluated - its result is 3; as a side effect b is decremented, and
the result of the expression is 1
both a || c-- and c && b-- evaluate to 1
The values of a and c are unchanged (1 and 1, respectively), while b has been decremented and its value is now 2.
You can imagine this if statement
if((a||c--)&&(c&&b--)) printf("%d",b);
the following way
if ( a )
{
if ( c )
{
if ( b-- )
{
printf("%d",b);
}
}
}
else if ( c-- )
{
if ( c )
{
if ( b-- )
{
printf("%d",b);
}
}
}
So if the expression in the first if statement
if ( a )
evaluates to the logical true then this if statement
else if ( c-- )
never gets the control.
From the C Standard (6.5.14 Logical OR operator)
4 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.

Using logical operators on integers in C

Logical OR and Logical AND operator on integers in C
Can you explain me why the values of a,b,c are 11,10,1 respectively.
Why the value of b remains same as 10?
#include <stdio.h>
int main()
{
int a,b,c;
a=b=c=10;
c = a++ || ++b && ++c;
printf("%d %d %d",a,b,c);
return 0;
}
First, let's look at the order of operations. The logical AND operator && has higher precedence than the logcial OR operator ||, so the expression parses as follows:
c = a++ || (++b && ++c);
Next, both || and && are short circut operators. This means that the left has side is evaluated first, and if the result can be determined solely from that then the right hand side is not evaluated.
So a starts out with the value 10. a++ evaluates to the current value (10) while incrementing a as a side effect. This means the value 10 is the left hand side of ||. Because this is a non-zero value, the value of the entire expression is 1 and the right hand side ++b && ++c is not evaluated. Then this result is assigned to 1.
So the end result is a is incremented to 11, c is assigned 1 because that is the value of the || expression, and b is unchanged.
This expression
c = a++ || ++b && ++c;
can be equivalently rewritten like
c = ( a++ ) || ( ++b && ++c );
As the expression a++ is not equal to 0 then the second sub-expression ( ++b && ++c ) is not evaluated.
The value of the logical operator || and && is either 1 (true) or 0.
From the C Standard (6.5.14 Logical OR operator)
3 The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
and
4 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.
So c gets the value 1 and a was increased.
Expanding, a little bit, on the other answers, you have to understand what your statement is actually doing.
a=b=c=10;
c = a++ || ++b && ++c;
The logical operators take, naturally, boolean operands, so your statement is (implicitly):
c = ( a++ != 0 ) || ( ++b != 0 ) && ( ++c != 0 );
Note, interestingly, that the order of precedence places the AND operator higher than the OR operator - which implies that ++b should be executed.
However, given the short-circuit operation of logical-OR, the first term is known to be true therefore c = 1 (ie true).
--
Regular readers will, of course, expect me to add a MISRA slant to my answer...
MISRA C:2012 Rule 13.5 covers this exact scenario... it states that The right hand operand of a logical && or || operator shall not contain persistent side effects
So a MISRA Compliant version of your code would be:
a=b=c=10;
a++;
b++;
c++; // This is actually *dead code*
c = a || ( b && c );
printf("%d %d %d",a,b,c);

What should be the value of b in the following code snippet and why? '-6' or '-7' [duplicate]

This question already has answers here:
C operator precedence, logical vs unary in a++ && b++ || ++c
(1 answer)
Require explanation for the output
(4 answers)
Precedence of && over || [duplicate]
(4 answers)
Closed 3 years ago.
I want so see the values of the four variables (Basically checking the precedence order of logical operators).
#include<stdio.h>
int main()
{
int a=0, b=-7, c=0, d;
d = ++c || ++a && ++b ;
printf("\n %d %d %d %d",a,b,c,d);
}
I expect the result to be '0 -6 1 1', but the actual output is '0 -7 1 1'. Can anyone please give an explanation behind the output shown?
First have a look at Operator Precedence.
Then, regarding the working of logical OR operator, from C11, chapter §6.5.14 (emphasis mine)
[...] 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.
and regarding the result:
The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
So, in your code
d = ++c || ++a && ++b ;
is the same as
d = (++c) || (++a && ++b);
which evaluates to
d = 1 || (++a && ++b); // short circuit, RHS not evaluated
which is finally same as
d = 1; // 1 is not the value computation of `++c`, rather result of the `||` operation.

Logical operators' precedence in C [duplicate]

This question already has answers here:
Precedence of && over || [duplicate]
(4 answers)
Closed 4 years ago.
#include <stdio.h>
int main(void) {
int a = 0, b = 0, c = 0;
++a || ++b && ++c;
printf("%d %d %d", a, b, c);
return 0;
}
The outputs are 1, 0, 0 by gcc 8.1.0. The &&‘s precedence should higher than ||.
Why are the b and c are still 0?
The expression ++a || ++b && ++c is grouped as ++a || (++b && ++c). But, the right hand side of || is only evaluated if ++a is 0, which it isn't.
There are three issues here:
Order of precedence.
Order of evaluation.
Short circuiting of logical operators.
Order of precedence implies that ++a || ++b && ++c is evaluated as ++a || (++b && ++c).
However, due to the short circuiting requirements of logical operators, ++a is evaluated first. Only if that evaluates to false will (++b && ++c) be evaluated. In your case, ++a evaluates to true. Hence, (++b && ++c) is never evaluated.
The logical OR operator || (as well as the logical AND operator &&) is one of the few operators that perform short circut operation.
Section 6.5.14 of the C standard says the following about the logical OR operator:
4 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.
Because ++a evaluates to 1, the result of the || operator is guaranteed to be 1 and the right hand side is not evaluated. Also, because && has higher precedence than ||, the right side of the || operator is ++b && ++c, meaning that neither ++b or ++c is evaluated.
Precedence only controls how expressions are parsed, not how they are evaluated. Arithmetic * has higher precedence than +, so a * b + c is parsed as (a * b) + c. However, each of a, b, and c may be evaluated in any order. The result of a * b must be known before it can be added to the result of c, but that doesn't mean that a * b must be evaluated before c.
Secondly, unlike most operators in C, the || and && operators force left-to-right evaluation. An expression like a || b && c will be parsed as a || (b && c), but a will always be evaluated first, and b && c will only be evaluated if the result of a is 0.
As far as precedence goes, x || y && z acts just like x + y * z: the second operator binds more tightly than the first one, and those expressions are equivalent to x || (y && z) and x + (y * z), respectively.
The reason that b and c in the question aren't incremented is because, in addition to precedence, logical operations short circuit: once you've gotten far enough along to know the result, the rest of the expression is skipped. Both || and && evaluate their arguments left-to-right, so in a() || b() and in a() && b(), the call to a() occurs before the call to b().
In simple cases, if a() returns true, then in the expression a() || b() the call to b() will not be executed, because it won't affect the result. Similarly, if a() returns false, then in the expression a() && b(), the call to b() will not be executed.
In the code in the example, the increments to b and c won't be performed, because ++a produces a non-zero value, so the result of the expression is true without needing to evaluate anything after ++a.
Operator precedence has nothing to do with order of evaluation. Precedence is the priority for grouping different types of operators with their operands.
So, the expression
++a || ++b && ++c;
will be evaluated as
++a || (++b && ++c);
Logical AND and Logical OR operator constitute sequence points and therefore guarantee a particular order of evaluation for their operands which is left to right.
Order of evaluation:
Ordering
......
If a sequence point is present between the subexpressions E1 and E2,
then both value computation and side effects of E1 are
sequenced-before every value computation and side effect of E2
Rules
.....
2) There is a sequence point after evaluation of the first (left) operand and before evaluation of the second (right) operand of the following binary operators: && (logical AND), || (logical OR), and , (comma).
Logical OR operation (expr1 || expr2) employs short-circuiting behavior. That is, expr2 is not evaluated if expr1 is logical 1 (true).
The initial value of a, b and c is 0. In the expression:
++a || ++b && ++c;
++a -> pre-increment a.
That means, the value of the expression ++a is resulting incremented value of a which will be 1. Since, || operator employs short-circuit behavior, the right hand side expression of || will not be evaluated. Hence, you are getting output - 1 0 0.
For better understanding, just try to change the ++a -> a++ in the expression.
The post increment operator also increase the value of operand by 1 but the value of the expression is the operand's original value prior to the increment operation. So, a++ will be evaluated to 0 and because of short-circuit behavior the right hand side expression of || operator (++b && ++c) will be evaluated.
The logical AND operation (expr1 && expr2) also employs short-circuiting behavior. With logical short-circuiting, the second operand, expr2, is evaluated only when the result is not fully determined by the first operand, expr1. That is, expr2 will be evaluated only if expr1 is logical 1 (true) and ++b will result in 1. So, if you do
a++ || ++b && ++c;
^^^
The output would be - 1 1 1.

An example about operator precedences

As far as I'm aware of, unary operators have prior precedence over || and &&. In the following code, I'd expect an output where all outputs are equal to 1. Yes, there is a short-circuit but shouldn't those pre-increments calculated before || and &&? How these precedences work here?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 0, b = 0, c = 0;
a = b = c == 1;
c = ++a || ++b && ++c; // short-circuit here
printf("a=%d, b=%d, c=%d\n", a, b, c);
}
Output:
a=1 b=0 c=1
Operator precedence doesn't have any relation with order of evaluation. Higher precedence means that grouping of operands to that operator is done first.
In the statement
c = ++a || ++b && ++c;
the grouping/binding of the operands of ++ will be done first and then that of && and || respectively. To show this I am adding parenthesis to the expression
++ has higher precedence so bind operand to it first
c = (++a) || (++b) && (++c);
&& has higher precedence than ||
c = (++a) || ((++b) && (++c));
|| has higher precedence than =
c = ((++a) || ((++b) && (++c)));
= has least precedence of all
(c = ((++a) || ((++b) && (++c))));
The fact that || is short-circuiting and the lowest precedence operator explains the result. Because ++ is the higher precedence than && and && is higher precedence than ||, the expression tree for ++a || ++b && ++c is:
|| -- left: ++a
-- right: && --left: ++b
--right: ++c
So, to evaluate the expression, C first considers the rules for evaluating ||, given by 6.5.14 in the C11 standard. Specifically:
6.5.14.4: 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.
The fact that || is short-circuiting means that it evaluates its left operand first and only evaluates its right operand if the left is zero. So to evaluate the expression ++a || ++b && ++c, C requires the following:
Evaluate ++a (a is incremented by one and the expression is equal to its incremented value). If it is non-zero, then || expression is equal to 1 and the right side is never evaluated.
Otherwise, evaluate ++b and ++c, in left-to-right order. If ++b is zero, then ++c is never evaluated. If both are non-zero, then the expression is equal to 1.
Because ++a evaluates to 1, the right side of the || is never evaluated. This is why you have a==1, b==0, and c==1.
There's one additional problem with the statement c = ++a || ++b && ++c, which is that there's a potential for the statement to invoke undefined behavior. If ++a is false and ++b is true, then ++c has to be evaluated. However, there is no sequence point between c = ... and ++c. Since the expressions both modify c with no sequence point in between, the behavior is undefined. For a further explanation of this see, for example, https://stackoverflow.com/a/3575375/1430833
I think you're confusing operator precedence with order of evaluation. Here's an outline of what happens. In the comments, my use of = is that of identity - much like the mathematical equals sign.
#include <stdio.h>
#include <stdlib.h>
int main()
{
// all variables are assigned the value 0
int a = 0, b = 0, c = 0;
// a and b are equal to the evaluation of `c == 1`, which is false. a and b are 0
a = b = c == 1;
/*
&& has higher precedence than ||, so ++b and ++c are "grouped": ++a || (++b && ++c)
++a is evaluated, a = 0+1 = 1. 1 is true, short circuit the second grouping.
c = a = 1.
*/
c = ++a || ++b && ++c; // short-circuit here
// a = c = 1, b = 0
printf("a=%d, b=%d, c=%d\n", a, b, c);
}

Resources