Logical Expressions in C misunderstanding - c

So, I was writing some code and I was getting an unexpected output in one part of my program which disrupted the entire system.
I managed to extract and simplify the problem to a basic logical expression. Let's say:
int i = 1, j = 1, k = 0;
printf("%d\n", ++i || ++j && k);
printf("%d, %d, %d\n", i, j, k);
return 0;
The output for this program is:
1
2 1 0
I am thinking that the value of j was not incremented to 2 due to the short circuit nature of the || operator. However I am confused how the value of the first "%d" is 1. Shouldn't the value of k be non-zero for the && statement to return 1? Or isn't this statement executed at all since ++i || ++j is not 0 and thus returns a 1?
I know that && is a logical and, and expr1 && expr2 has the value 1 if values of expr1 && expr2 are both non-zero.
Any clarifications would be appreciated and please excuse the basic nature of this question.

&& has higher precedence than ||.
(See https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B )
so
++i || ++j && k
is
++i || (++j && k)
and || shortcircuits if the first operator is truthy, as per 6.5.14p4 .
If you're on gcc or clang and compile your code with -Wall, the compiler will nudge you to put those parentheses there. It's probably a good idea to heed that advice, as some people get confused by the precedences (I hear).

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.
This expression
++i || ++j && k
is equivalent to
++i || ( ++j && k )
and according to the quote from the Standard the expression returns integer value 1 because ++i is not equal to zero. The subexpression ( ++j && k ) is not evaluated.

++i || ++j && k is evaluate to 1 (true) because i equals 2 (++1), (++j && k) isn't evaluated because short circuit.

Operators precedence. && has higher precedence than ||.
Your expression is the same as: ++i || (++j && k)
++i is TRUE, the parenthesis is not evaluated anymore.

Related

Difference between i++ and ++i?

This is My Code:
int main()
{
int i=2,j=2,c=2,d;
d= ++i || ++j && c;
printf("I is %d\n",i);
printf("J is %d\n",j);
printf("C is %d\n",c);
printf("D is %d\n",d);
return 0;
}
The output of the following code is:
i is 3
j is 2
c is 2
d is 1
Now my question is, if ++i is 3 then why ++j is 2?
What is the difference between ++i & i++? Also I want to know that how come d is 1 ?
You asked:
Now my question is if ++i is 3 then why ++j is 2?
++j is never executed since ++i evaluates to true.
The expression ++i || ++j && c is equivalent to ++i || (++j && c) due to operator precedence.
The run time evaluates the expression ++i || ++j && c from left to right.
The first term, ++i evaluates to 3, with the side effect that the value of i is 3. Since it is non-zero, the run time does not need to evaluate anything after that. Since ++j is never evaluated, the value of j is not changed.
What is the difference between ++i & i++?
The value of the expression ++i is i+1 with the side effect that the value of i is incremented by 1.
The value of the expression i++ is i with the side effect that the value of i is incremented by 1.
int i = 2;
int x = ++i; // x == 3, i == 3 at the end of execution of the statement
int y = i++; // y == 3, i == 4 at the end of execution of the statement
I want to know that howcome D is 1
The value of d is set to 1 since the boolean value of the expression is true.
++i is pre increment.
i++ is post increment.
Suppose here i = 2
In Post In crement
printf("%d",i++); // it will print output 2 then increment value of i to 3
In Pre Increment
printf("%d",++i); //first it will increment value of i to 3, then print output 3
d= ++i || ++j && c;
Condition will be performed in this manner ++i || (++j && c);
As i=2, after ++i it will become 3.
In OR if first condition is true it will skip second condition. means ++j && c will not be performed.
Result of ++i || ++j && c is 1
so d = 1.
printf("I is %d\n",i); // i = 3;
printf("J is %d\n",j); // j = 2;
printf("C is %d\n",c); // c = 2;
printf("D is %d\n",d); // d = 1;
Short Circuit evaluation
Reason for the evaluation is short-circuiting of the boolean operators && and ||.
For &&, if the left-hand side expression is false, the combined result is false (the right-hand side expression is never evaluated).
For ||, if the left-hand side expression is true, the combined result is true (the right-hand side expression is never evaluated).
This is mostly important when the right-hand expression has side effects, such as altering values(or calling some functions with side-effects), for example in your case:
d= ++i || ++j && c;
Note that the combined conditional expression would increment i by 1 since the conditional expression on the left of || is true, the conditional expression on the right-hand side i.e. ++j && c is never evaluated.
Thus, the total expression will lead eventually to:
d = 1 || ++j && c;
which explains why d=1?
Now if you change the value of i=-1 then the expression on the right of the || will be executed and the j will be incremented as per your expectation
Now for the performance effects of i++ vs ++i check here :)

Understanding operators in C [duplicate]

This question already has answers here:
OR and AND operation in C
(2 answers)
Closed 7 years ago.
I am struck on a basic problem with operators. Here is the problem
int i=3, j=2, k=1, m;
m = ++i || ++j && ++k;
printf("%d %d %d %d", i, j, k, m);
As i worked on this and evaluated the ans as
4 3 2 1
But C is not happy with my ans and evaluates the above as
4 2 1 1
But i dont understand how. Why ++j is doesn't updates the value of j. And also ++k doesn't updates the value of k.
Anybody here please explain this how it worked.
m = ++i || ++j && ++k;
The && operator has higher precedence than ||, so this is equivalent to:
m = ++i || (++j && ++k);
Both && and || are short-circuit operators; if the left operand determines the result, the right operand is not evaluated. Since ++i (which yields 4) is "truthy", the right operand (++j && ++k) is not evaluated, and j and k are not incremented. So i becomes 4, and j and k retain their initial values of 2 and 1, respectively.
The result of the || operator is either 0 (for false) or 1 (for true); since the condition is true, the value 1 is assigned to m.
Result:
4 2 1 1
In C, || is a short-circuit operator. This means when evaluating the expression a || b, it will only evaluate b if a is false. If a is true, then the expression will always be true regardless of b.
Since ++i gives a truthy value, ++j && ++k will not be evaluated.

C program logic operator sequence

why would the second line
int i=-3, j=2, k=0, m;
m = ++i && ++j || ++k;
terminate after ++j and ignore ++k ?
I know the first half make TRUE value and would return TRUE whatever the following value is. But what is the condition to stop executing following instrument? As long as we can confirm the final value?
&& has higher precedence than that of ||. ++i and ++j binds to it and
m = ++i && ++j || ++k;
is parsed as
m = (++i && ++j) || ++k;
Since both the sub-expressions ++i and ++j are non zero, it is interpreted as true. Due to short circuit behavior of logical operators second (right) sub-expression is not evaluated in case of || if left becomes true.
Note that the left sub-expression for || is (++i && ++j), not j++.
The condition is exactly that. In an OR in C, whenever the result is found to be true, none of the rest of expressions are even evaluated.
If you want to test true or false and also be sure that the variables involved are increased, you should instead increase the variables before and then test:
++i;
++j;
++k;
m = i && j || k;
The || operator does not evaluate the second operand if the first operand evaluates TRUE.
And the && operator does not evaluate the second operand if the first operand evaluates FALSE.
The operands of logical-AND and logical-OR expressions are evaluated from left to right. If the value of the first operand is sufficient to determine the result of the operation, the second operand is not evaluated. This is called "short-circuit evaluation." There is a sequence point after the first operand. See Sequence Points for more information.
Get the answer you want: here

Output of following code [duplicate]

This question already has answers here:
Why isn't "k" incremented in the statement "m = ++i && ++j || ++k" when "++i&&++j" evaluates to true? [duplicate]
(5 answers)
Closed 9 years ago.
#include<stdio.h>
int main()
{
int i=-3,j=2,k=0,m;
m= ++i && ++j || ++k;
printf("%d %d %d %d",i,j,k,m);
return 0;
}
Could someone tell how does is the m evaluated. I am confused as how k remain '0'
m= ++i && ++j || ++k;
First, ++i && ++j takes effect, i become -2 and j become 3, which makes ++i && ++j non-zero, so m will be evaluated to 1 (true) because of short-circuit. All the later expression(++k) won't be executed.
m= ( (++i) && (++j) ) || ++k;
| |
| |
( T (-2) AND T(3) ) OR something
^^^^^^^^^^^^^^^^^
T OR something
^^^^^^^^^^^^^^^^^^^^^^^^^
= T
= 0
Changing j=-1
m= ( (++i) && (++j) ) || ++k;
| |
| |
( T (-2) AND T(0) ) OR something
^^^^^^^^^^^^^^^^^
F OR T (0) //++k evaluated
^^^^^^^^^^^^^^^^^^^^^^^^^
= T
= 0
Initialized Values:
int i=-3,j=2,k=0,m;
Original expression:
m= ++i && ++j || ++k;
With implicit operator precedence:
m= (++i && ++j) || ++k;
The expression evaluates left to right. What you need to understand is how Short Circuit Logic works.
Evaluation Walkthrough:
i gets incremented (-3 --> -2)
The logical AND operator is evaluated (&&). It checks if the left hand argument i evaluates to true (i!=0). If the left hand side evaluates to false, the and operator short circuits the evaluation and returns false (0). This doesn't happen because i==-2, so the right hand side (++j) is also evaluated.
j get incremented (2 --> 3)
Logical AND finishes its right hand side evaluation i!=0 && j!=0. It returns true (!0).
The logical OR operator is evaluated (||). It checks if the left hand argument (++i && ++j) evaluates to true (!0). If the left hand side evaluates to true, the and operator short circuits the evaluation and returns true (!0). This happens because ++i && ++j already evaluated true. Consequent k++ never executes!
Logical OR (||) assigns the evaluated value (!0) to m. m!=0 after the expression evaluates.
This is because of short circuting. If you know about how an OR expression is evaluated, you will get the hang of this expression. 1 OR Anything is always 1
int i=-3,j=2,k=0,m;
m= ++i && ++j || ++k;
`-2 && +3 is +1 therefore +1 OR anything is 1.` Hence C skips evaluation of k.
the answer would be
-2 3 0 1
Explanation :
There are two basic facts that work here
FACT 1 :
Whenever there is an expression with PRE-INCREMENT operator, All these operators would be operated on the corresponding variables first, and then the whole expression would be evaluated with updated values of variables.
FACT 2
whenever there is an expression having OR operator, If first operator is true(or non zero in some cases), second operator wouldn't be executed.
for example
a=2;
b=2;
c=3;
boolean k = c || a+b ;
The values of variable k would be true and the expression "a+b" wouldn't be even considered as c is non zero.
In your case variable i and j would be incremented first and the expression would be
-2 && 3 || ++k
Note : variable k wouldn't be incremented here because in case of OR logical operator Left operand would be solved completely first.
Left operand would would be then TRUE because both -2 and 3 are non zero .
so the whole expression would be
TRUE || ++k
This wouldn't be evaluated further because no matter what, the result always be TRUE .
as we are assigning this result (TRUE) to an integer variable, it would be 1.
Hence the answer is ....

Please explain an apparent conflict between precedence of && and || and the actual result of an expression [duplicate]

This question already has answers here:
Precedence of && over || [duplicate]
(4 answers)
Closed 8 years ago.
I don't understand the output of the following program:
#include<stdio.h>
int main()
{
int i=-3, j=2, k=0, m;
m = ++i || ++j && ++k;
printf("%d %d %d %d\n", i, j, k, m);
return 0;
}
The output is -2 2 0 1 instead of -2 3 1 1, implying that ++i was evaluated (and caused the || operator to short-circuit its right hand side) before the expression ++j && ++k which appears to contradict the fact that the && operator has higher precedence than ||.
Would someone explain why?
The output should be something like:
Error, line 2: 'm': undefined variable.
Edit: with that fixed, only the ++i should be evaluated. Precedence does not determine (or even affect) order of evaluation. Precedence means the expression is equivalent to ++i || (++j && ++k). Order of evaluation for || or && is always that the left operand is evaluated, then there's a sequence point. After the sequence point, the right operand is evaluated if and only if necessary to determine the final result (i.e., the right operand of || is evaluated if the left operand evaluated to zero; the right operand of && is evaluated if the left operand evaluated to non-zero).
In this expression, ++i is evaluated, then because it's the left operand of || and evaluated non-zero, none of the rest of the expression is evaluated.
-2 2 0 1
Lazy.
#include <stdio.h>
int main()
{
int i=-3,j=2,k=0;
int m=++i||++j&&++k;
printf("%d %d %d %d",i,j,k,m);
}
Compile, run and see for youself.
gcc tmp.c -o tmp
The expression:
++i || ++j && ++k
Is equivalent to:
(++i) || ((++j) && (++k))
Explaining:
++i is evaluated -- (-2) || ((++j) && (++k));
The || operator is evaluated -- (1);
Since 1 || anything evalutes true, the right operand is not evaluated. Thus, the && precedence doesn't matter here. This short circuiting is guaranteed in both C and C++ by the relevant standards (see Is short-circuiting logical operators mandated? And evaluation order?).
Now, try using a sub-expression, like this:
(++i || ++j) && ++k
Which is equivalent to:
((++i) || (++j)) && (++k)
Explaining:
++i is evaluated -- ((-2) || (++j)) && (++k);
|| is evaluated -- (1) && (++k)
++k is evaluated -- (1) && (1);
Evaluates true;
By way of explanation:
#include <stdio.h>
int main()
{
if (-1)
printf ("-1!\n");
else
printf ("Not -1.\n");
return 0;
}
Negative numbers are not false in C. Always compare boolean values to 0 (or FALSE) or you can get bitten by if (worked == TRUE) giving false negatives.

Resources