Why doesn't ++i || ++j && ++k give the expected value - c

I want to know why the value of k is 1 in the below code.
I think ++i || ++j && ++k is executed along the order:
((++i || ++j) && ++k)
So, in the first fragment, (++i || ++j), ++i is true, so ++j is not evaluated, so i=2, j=1.
Next, in the second fragment, (true && ++k), so ++k is evaluated, and then k=2.
#include <stdio.h>
int main(void)
{
int i, j, k;
i = 1; j = 1; k = 1;
printf("%d ", ++i || ++j && ++k);
printf("%d %d %d\n", i, j, k);
return 0;
}
But,
printf("%d %d %d\n", i, j, k);
shows
2 1 1
I don't know what was mistaken or what I've misunderstood.

The logical AND operator && has higher precedence than the logical OR operator ||. So the expression is actually parsed as:
++i || (++j && ++k)
++i evaluates to true so the entire right side of the ||, i.e. ++j && ++k, is not evaluated. This results in neither j nor k being incremented.
It can be difficult to remember all the precedence rules, both for yourself and for others who read your code. So when in doubt, use parenthesis to clarify your intentions.

Running with compiler warnings, or a good editor like Atom.io, reveals the problem.
cc -Wall -Wshadow -Wwrite-strings -Wextra -Wconversion -std=c99 -pedantic -g `pkg-config --cflags glib-2.0` -c -o test.o test.c
test.c:8:30: warning: '&&' within '||' [-Wlogical-op-parentheses]
printf("%d ", ++i || ++j && ++k);
~~ ~~~~^~~~~~
test.c:8:30: note: place parentheses around the '&&' expression to silence this warning
printf("%d ", ++i || ++j && ++k);
^
( )
1 warning generated.
It's a precedence issue. Operators in an expression are not evaluated left-to-right but rather in precedence order. ++i || ++j && ++k is being evaluated as ++i || (++j && ++k) because && has a higher precedence than ||.
To avoid these issues, turn on compiler warnings and make it a habit to put parens around anything that might be ambiguous.

Related

How the following relational expression written in if-else statement is understood by the C Compiler?

I am unable to understand why this code is displaying 20 30 40 as output. Can anyone explain how the relational expression written in if statement is understood by the C Compiler ?
This is the image of code of the C Program
#include <stdio.h>
int main()
{
int i = 20, j = 30, k = 40;
if (i > j == k)
{
printf("%d %d %d ",--i,j++,++k);
}
else
{
printf("%d %d %d ",i,j,k );
}
return 0;
}
Output:
20 30 40
first thing to consider is operator precedence. the operator > is evaluated before the operator == and it returns a value. in this case, i > j is wrong so it returns zero. then it checks if zero equals to k which is 40 and it isn't. so it goes to else branch.
According operator precedence i > j == k is executed as (i > j) == k
So i > j is executed first, returning a boolean (here, false, ie 0)
And result is compared to k, which is not equal to 0. Condition is than false, so else part of condition is executed

C Program Output Complexity

Could you please explain why the following program is giving such outputs?
#include<stdio.h>
int main()
{
int i=-3,j=1,k=0;
int m;
m=++i || ++j && ++k;
printf("i= %d\nj=%d\nk=%d\nm=%d", i,j,k,m);
return 0;
}
Output:
i= -2
j=1
k=0
m=1
Since ++i is essentially true, because it is not 0, therefore the || other part will not be evaluated, since it does not matter at this point, the expression is true. Therefore j and k will not change. true is 1, that is why m is 1.

Effect of the ||-operator on ++x

#include<stdio.h>
int main()
{
int i=0, k=0, m;
m = ++i || ++k;
printf("%d, %d, %d\n", i, k, m);
return 0;
}
returns
1,0,1
Why is k = 0 and not 1? what is the effect of the ||-operator on the ++k?
Thanks!
example: https://ideone.com/Fjsbii
In || OR , if first condition is true, it will not check second condition.(it will skip 2nd condition).
As
m = ++i || ++k;
in this condition after ++i, value of i will become 1, as first condition is true, so it will skip second condition. so the operation ++k will not be performed.
And hence k will remain 0.
Same as if you are using && , and first condition is false it will skip second condition. and result will be 0 (false).

Why The Value Of K is Not Increasing in this code?

#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 value of k increases if i am using a || operator but in case of && the value is not increasing what would be the reason for that , i am very confused.
The out put is -2,3,0,1
You have a test in your code:
m = ++i && ++j || ++k;
When you use multiple tests like this, you will first evaluate ++i && ++j. If it's true, you will never evaluate the || ++k part (because m would be true anyway). This is called lazy evaluation.
If ++i && ++j had been false in your example, k would have been increased because the last part of the test would have been evaluated.
if the operators of “&&”are not zero,it will come true,then the rest part will not be used.
In c,if it is not zero,it is true.
It is called lazy evaluation. false && b is always false whatever b might be.
In your case:
m = ++i && ++j || ++k; evaluates to m = true || ++k; which leads to ++k not being evaluated because of lazyness.
Because ++k is not evaluated as ++i && ++j evaluates to true.
The OR condition is lazily evaluated.
The ++k is never executed, because the first part of the condition is not true.
expressions after || when the values before it evaluate to true will NOT be evaluated.
(c=10)|| (y=20)
In this example, c=10 evaluates to true, due to which y=20 will not be evaluated.

What will the following code evaluate?

I had the following code in a test.I am confused about what (i,j) evaluates,while reading about the "," operator i found that it just evaluates the variables or functions but what does it do here?
main()
{
int i = 10, j = 20;
j = i ? (i, j) ? i : j : j;
printf("%d %d", i, j);
}
(i,j) is exactly the same as just j, because i is just a variable and evaluating it doesn't cause any side effect.
So basically it's just obfuscation here.
in (i,j), the , operator does nothing because the left-hand side expression does not have side-effects.
The assignment is thus equivalent to:
j = i? (j? i : j) : j;
And since i and j are non-zero, to j = i;
The comma operator can be used to link the related expressions together. A comma-linked list of expressions is evaluated left-to-right and the value of the rightmost expression is the value of the combined expression. It acts as a sequence point.
A sequence point guarantees that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.
So, any expression/assignment will be completed & only then will the next expression to the right be evaluated.
For example,
b=(a=4,a=5);
gives,
a=5
b=5
Also, note that the comma operator ranks last in the precedence list of operators in C.
It will print:
10 10
This is because you can break the expression down like:
j = i ? ((i, j) ? i : j) : j;
The comma operator evaluates to the last expression - so (i, j) == j. That is non-zero, so the center expression evaluates to i. 'i' being non-zero, the outer expression evaluates to i, so j is assigned to the value of i.
This is equivalent to:
int main() {
int i = 10, j = 20;
if (i != 0) {
(void)i; // Do nothing with i.
if (j != 0) {
j = i;
} else {
j = j; // Assign j to itself.
}
} else {
j = j; // Assign j to itself.
}
printf("%d %d", j);
}
Looks like typical software written test question. It is used to confuse candidates. As suggested by sepp2k above it is same as j. One more interview question
i = 10; j = 20;
1) k = i,j;
2) k = (i,j);
Answer for 1 will be 10 and answer for 2 will be 20. As coma operator doesnt do anything. I hope this will clear more.
It's not really doing anyting. It's evaluating the expression i, discards the result, evaluates the expression j and returns the result.
As evaluating the expression i has no side effects, (i,j) has the same meaning as just j.
main()
{
int i = 10, j = 20; // i=10, j=20
j = i ? /*if i */ ( (i, j) ? /* if j (1) */ i : /* else */ j ) : /* else */ j; // Added parenthesis and see (2)
printf("%d %d", i, j); // Will therefore print 10 10
}
it is equivallent to if(j) because (i,j) evaluate to j because i has no side effect.
all ifs evaluate to true because i and j are ints and are non zero

Resources