Finding logic for this output - c

Explain how this output comes.
#include <stdio.h>
int main()
{
int x,y,z;
x = y = z = -1;
z = ++x && ++y && ++z;
printf("%d %d %d", x, y ,z);
return 0;
}
I thought x,y,z all values will be 0 but the actual output is x=0,y=-1,z=0.

There are two things that are involved here: Operator associativity, and short-circuit evaluation (please see the link for a description of what it is and what it does).
Due to the associativity of the && operator, the expression ++x && ++y && ++z is equal to (++x && ++y) && ++z.
If we do the sub-expression ++x && ++y then the result is false. What happens is that ++x results in 0, so we have 0 && ++y. And in C zero is the same as boolean false, and due to the short-circuit evaluation ++y never happens. The value of y stays at -1.
So with the result of the first sub-expression, we have false && ++z. Again due to short-circuit evaluation ++z never happens, and the result is again false.
So the result of ++x && ++y && ++z is false, which is then assigned to z. And in the assignment the boolean false is implicitly converted to the integer value 0. Which is the printed value of z.

You have a incorrect declaration to start with, the last variable in the declaration should have been z instead of x back again (corrected since the last edit)
As for the result, you would see an output 0 -1 0, because after the first pre-increment, the value of x becomes 0 and the evaluation short-circuits ( operand right to && is not evaluated) as 0 && ++y producing integer 0 and pre-increment on y never happening at all. The expression now becomes 0 && (++z) which would short-circuit again to produce 0
The result of the final expression z when printed with %d specifier becomes 0.

From this link I can read
The ‘&&’ operator doesn’t evaluate second operand if first operand becomes zero.
z = ++x && ++y && ++z = ((++x && ++y) && ++z)
Inner parenthesis (++x && ++y)
++x = -1 + 1 = 0 second operand ++y is not evaluated, y = -1, z = -1
Outer parenthesis
((++x && ++y) && ++z) = (0 && ++z)
Again ++z is not evaluated z remains -1
++x && ++y && ++z = 0 and x = 0, y = -1, z = -1
Then you overwrite the value of z by assigning ++x && ++y && ++z = 0 to z
so the old value of z namely -1 is replaced by ++x && ++y && ++z namely 0
Finally
x = 0, y = -1, z = 0

Related

A specific short-circuiting example in C

I understand the basic concept of short-circuiting with operators, but why does
int i = 0, j = -1, k = 1, m;
m = !(i++ && ++j) || ++k;
printf("%d %d %d %d", i, j, k, m);
have 1 -1 1 1 as an output? Specifically, why is j == -1 instead of 0?
I know similar questions have been already asked, but I don't understand this specific example which I didn't find anywhere.
i = -1;
i++; // value of expression is -1
// side effect is changing i to 0
if (i++) ; // value of `i++` is zero; the if will not "trigger"
i = 0;
if (i++ && foo) ; // i++ has value of zero (false)
// so false && <anything> is false
// so foo is not evaluated
int i = 0, j = -1, k = 1, m;
!(i++ && ++j) || ++k; ==> only i++ will be evaluated, j and k will not be evaluated
lets just say we are substituting the values of variables, then the expression becomes as below.
!(0 && ++ -1) || ++1
step 1:
!(0 && ++ -1) ==> for && operator if left side operand is False then we dont need to check for right side operand, so -1 wont be incremented, so value of j will be -1 itself.
and hence the left side expression before || becomes !(0)
step 2:
!(0) || ++1
now !(0) will be 1 , so for || operator if left side operand is TRUE , then no need to go for right side operand, then ++k will not be executed.
m = 1 || ++1 ==> 1
since only i++ is evaluated , it will change its value to 1
so the out put is : 1 -1 1 1
The value of the postfix increment operator is the value of its operand before incrementing.
So the value of the expression i++ is equal to 0 because the variable i was initialized by 0.
So as the value of the sub-expression i++ is 0 then the sub-expression ++j in this expression
(i++ && ++j)
is not evaluated and the value of the expression itself is 0.
Applying the negation operator
!(i++ && ++j)
you will get 1 (logical true). So the sub-expression ++k of the expression
!(i++ && ++j) || ++k
will not be evaluated.
As a result the value of the whole expression is equal to 1 that is assigned to the variable m.
m = !(i++ && ++j) || ++k;
On the other hand as it was pointed out in the beginning the expression i++ was evaluated. So after this statement i will be equal to 1.

Multiple logical operators in one line of code

I was searching on Stack Overflow for the answer to this question but I haven't found an exact answer. I came up with this code. I know how operators are supposed to work but I don't understand them in this kind of problem. For example, in the first case, how can z and y still be 1 if there I am using ++y and ++z?
#include <stdio.h>
int main(void) {
int x, y, z;
x = y = z = 1;
++x || ++y && ++z;
printf("x = %d y = %d z = %d\n", x, y, z);
x = y = z = 1;
++x && ++y || ++z;
printf("x = %d y = %d z = %d\n", x, y, z);
x = y = z = 1;
++x && ++y && ++z;
printf("x = %d y = %d z = %d\n", x, y, z);
x = y = z = -1;
++x && ++y || ++z;
printf("x = %d y = %d z = %d\n", x, y, z);
x = y = z = -1;
++x || ++y && ++z;
printf("x = %d y = %d z = %d\n", x, y, z);
x = y = z = -1;
++x && ++y && ++z;
printf("x = %d y = %d z = %d\n", x, y, z);
return 0;
}
As results i get:
x = 2 y = 1 z = 1
x = 2 y = 2 z = 1
x = 2 y = 2 z = 2
x = 0 y = -1 z = 0
x = 0 y = 0 z = -1
x = 0 y = -1 z = -1
This is a result of the evaluation of the logical expressions: as soon as it has been determined that an expression is false (or true), the remaining operators are not evaluated anymore. E.g.:
++x || ++y && ++z;
As x is one, the expression will be true independent of what z or y are, so ++y and ++z are not performed anymore.
Due to precedence rules, the expression in the first example is identical to ( && has higher precedence than || ):
++x || ( ++y && ++z ) ;
So we're left with the operator || and its two operands ++x and ( ++y && ++z ). This operator is evaluated from left to right, so ++x is evaluated first.
But this operator also short-circuits, which means that if the first operand evaluates to true, as in this case ++x does, the second operand ( ++y && ++z ) won't be evaluated.
The reason is that you used || and &&.
&& and || operators short-circuit evaluations, that is, for && if the first operand evaluates to false, the second operand is never evaluated because the result would always be false. Similarly, for || if the result of the first operand is true, the second operand is never operated.
The single ampersand "&" can be said as "bit-wise AND" operator and The double ampersand "&&" can be mentioned as "Logical AND" operator.
for example, in this line:
++x || ++y && ++z;
x is 1 so the boolean value of ++x is true. because you used || the statment "++y && ++z" is not run at all and the value of y and z is 1.
if you will use & and | the value will increase to 2.

Behaviour of && in C programming language

I am beginner in C programming language, recently I have read about Logical AND && operator.
I also know that, in C programming language all non-zero values are treated as TRUE.
NON-ZERO && NON-ZERO = 1
NON-ZERO && ZERO = 0
ZERO && NON-ZERO = 0
ZERO && ZERO = 0
But when I am dealing with the following program then I am not getting expected answer.
int main(){
int x, y, z;
x = y = z = -1;
y = ++x && ++y && ++z;
printf("x = %d, y = %d, z = %d, x, y, z);
return 0;
}
I am expecting
x = 0, y = 0, z = 0
but the answer is
x = 0, y = 0, z = -1
Can anyone please explain, Why I am getting this answer?
Edit:
In this question, I have not asked about the precedence of operators.
Because of Short-circuit evaluation, when x is 0, y and z don't really need to be evaluated since 0 && ANYTHING is 0.
Once x is incremented to 0, the result is 0, and that's what y gets.
z remains unchanged (-1).
x | y | z
----+----+-----
-1 | -1 | -1 //x = y = z = -1;
0 | -1 | -1 //++x && ... Now the whole expression is evaluated to 0
0 | 0 | -1 //y = ++x && ++y && ++z;
I only can think about that && evaluates in short circuit: given A && B, if A evaluates false then B is not evaluated.
So:
X becomes 0. && ++y && ++z does not evaluates since X/0/false && ...
y=0 as assigned from y = x/0/false
z remains unmodified since ++z does not get executed.
&& operator is evaluated pairwise, therefore I'm guessing C is evaluating
((++x && ++y) && ++z)
now, ++x will return zero therefore the first && will fail as will the second one without the need to evaluate ++y or ++z.
y = 0 since that is the result of the expression.
z is not touched
What happens is that ++y and ++z are never evaluated because the first part already ensures what the new value of y will be.
The first part of your statement is ++x && ... which is equivalent to 0 && ... and then we already know that y will be 0 in the end so the rest of the statement is not executed.
if you did this:
int main(){
int x,y,z,tmp;
x = y = z = -1;
tmp = ++x && ++y && ++z;
printf("x = %d, y = %d, z = %d, tmp = %d", x,y,z, tmp);
return 0;
}
You would get x = 0, y = -1, z = -1, tmp = 0
The left evaluation is guaranteed in the C99 standard. You can find it in the section 6.5.13 Logical AND operator
Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation;
there is a sequence point after the evaluation of the first operand. If the first operand
compares equal to 0, the second operand is not evaluated.
You can find more information about what is a sequence point on Wikipedia or in the Annex C of the C99 standard
For completeness (brain dump):
The term behind this sorcery is called short circuiting. Let's go over your code and then a brief blurb about why this happens. Looking at:
int main( void ) {
int x, y, z;
x = y = z = -1;
y = ++x && ++y && ++z;
printf( "x = %d, y = %d, z = %d, x, y, z );
return 0;
}
... we begin to break it down line by line. The first line:
int x, y, z;
... declares three integers, x, y and z. They are initialized to garbage values on the stack frame because there is no initialization (assignment operator). This line does not really matter, now let's look at the next one:
x = y = z = -1;
... we see that we are doing multiple assignments on the same line. Recall that the assignment operator will mutate the identifier to the left of the assignment operator (using the value to the right of the assignment operator) and return the value of x. This is known as assignment overloading. But again, this does not really matter -- the only important thing to realize is x, y and z are now all -1. Let's look at the next line:
y = ++x && ++y && ++z;
... Sorcery Yoda says. Let's add the parenthesis to make it more obvious which step is being evaluated first:
y = ( ( ++x ) && ++y && ++z );
... now looking at the inner-most parenthesis we see that it's a prefix increment of x, meaning we will increment the value of x and then return it. We note that x is originally -1 and it is now 0 after being incremented. This will resolve as follows:
y = ( 0 && ++y && ++z );
... now it's important to note that looking at our truth tables:
A | B | A && B
--------------
T | T | T
T | F | F
F | T | F
F | F | F
... for the AND logical operator we see that both F (AND) T, T (AND) F are F. The compiler realizes this and short circuits when ever it is evaluating a conjunction (AND) where a value is false -- a clever technique of optimization. It will then resolve to assigning y to be 0 (which is false). Recall that in C any non-zero value is true, only 0 is false. The line will look as follows:
y = 0;
... now looking at the next line:
printf( "x = %d, y = %d, z = %d, x, y, z );
... it should be obvious to you now that it will output x = 0, y = 0, z = -1.

is the precedence of operator ignored in 'if' conditions

I'v a following code:
void main()
{
int k, x, y, z;
printf("\nExperiment 1:");
x = 0, y = 0, z = 0;
k = x++ || y++ && z++;
printf("\nx = %d, y = %d, z = %d and k = %d\n", x, y, z, k);
printf("\nExperiment 2:");
x = 1, y = 0, z = 0;
k = x++ || y++ && z++;
printf("\nx = %d, y = %d, z = %d and k = %d\n", x, y, z, k);
}
The output:
Experiment 1:
x = 1, y = 1, z = 0 and k = 0
Experiment 2:
x = 2, y = 0, z = 0 and k = 1
What I've understood is:
For the expression to be true, either left side or right side of '||' has to be non-zero. It starts from left. If left is non-zero, it doesn't evaluate further. If it is zero, it starts on right side. On right we have '&&'. So, we again start from left side of && and in case it is zero, the expression cannot be true and it doesn't proceed. Otherwise it evaluates the right side of '&&'
My assumption was operator && has higher precedence. So, both of its arguments should have been evaluated and then && should have been applied over it followed by evaluation of both arguments of ||.
Is compiler optimizing itself? I've used Visual Studio TC compilar with Optimization disabled.
I think this is covered in C11 by §6.5.14 Logical OR operator (my emphasis)
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 the expression
k = x++ || y++ && z++;
is interpreted as (due to precendence rules):
k = x++ || (y++ && z++);
In Experiement 1, we have x = y = z = 0;.
In Experiement 2, we have x = 1, y = z = 0;.
So, the right-hand side expression stops after evaluating y++, since the value of that is 0 and thus the boolean and cannot become true.

I can not understand the output of this c programming. Please any one help

#include <stdio.h>
int main () {
int x, y, z;
x = y = z = 1;
++x || ++y && ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 2 y = 1 z = 1
//why is 'x' only incrementd?
x = y = z = -1;
++x || ++y && ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 0 y = 0 z = -1
//why are 'x' and 'y' incremented?
x = y = z = 1;
++x && ++y || ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 2 y = 2 z = 1
//why is 'x' only incrementd?
x = y = z = -1;
++x && ++y || ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 0 y = -1 z = 0
//why are 'x' and 'z' incremented?
//Does this incrementation depend on the value stored in the variable?
}
The reason is that && and || short circuit.
That is, once they know what the end result of the boolean expression will be, they stop evaluating.
So, if you do 1 || x++, then x will never be incremented, because any non-zero boolean value is a true value.
Likewise, if you do 0 && x++, x++ never will get executed either.
See also:
Short-circuit evaluation on Wikipedia
|| and && short-circuit. What that means is that they perform as little work as possible to return their value, only executing the right side if the left side doesn't nail the answer.
For instance:
1 || anything();
In this case, anything() will never execute, because || can simply return as soon as it evaluates the 1; no matter what anything()'s return value, the return value of || in this expression can never be 0.
Similarly:
0 && anything_else();
Here, anything_else() will never execute, because && already knows that its value can never be anything but 0.
In your examples, the ++ preincrements don't actually affect the short-circuiting, except to hide the values that the boolean short-circuit operators are actually making their decisions on.
In general the answer to your questions is that if you have the code A||B
If A evaluates to true then B is NEVER evaluated.
So in your first case if ++x is true (in your case x==2 so it is true) then the rest of the expression is never evaluated
Similarly in the second case ++x evaluates to 0 which is false thus the second art of the expression ++y must be evaluated (and this also evaluates to 0 which is false); no wis a similar manner to the || operator if the first operand of the && operator is false then there is no need to evaluate the second operand - thus the third term is never evaluated.
The same logic can be applied to the third case.
This has to do with the way c short-circuits the || and && operators.
For example, if you have A && B, the program will evaluate A. If that turns out to be false, we already know the result will be false no matter what's in B, so B is never evaluated. If you have C || D and C evaluates to true, you know the result is true no matter what's in D, so D is never evaluated.
In this code, the increments of variables are used in conjugation with expressions.
This is to avoid using if-else structure.
Here is the examples where precedence of operators are clarified:
++x || (++y && ++z);
++x || (++y && ++z);
(++x && ++y) || ++z;
(++x && ++y) || ++z;
the expressions are evaluated from left to right.
In the first example, the program already know the whole expression will yield true after ++x, and the program will not bother to evaluate the rest of the expression. C uses something called short-circuit evaluation.
In C++ or C:
True is 1 or any non-zero value
False is 0 or any negative value
These conditions are short-circuited - so when C++/C comes across the first true part - it breaks and doesn't evaluate the rest.
x = y = z = 1;
++x || ++y && ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 2 y = 1 z = 1
//why is 'x' only incrementd?
x is true (2) and the rest of the condition is not evaluated
x = y = z = -1;
++x || ++y && ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 0 y = 0 z = -1
//why are 'x' and 'y' incremented?
x is false (0) so then y is evaluated which is false (0) - since it is false it is not checked further..
x = y = z = 1;
++x && ++y || ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 2 y = 2 z = 1
//why is 'x' only incrementd?
x is true (2 which is non zero)
y is true (2) - since x and y are true - the first part is true so it doesnt evaluate z.
x = y = z = -1;
++x && ++y || ++z;
printf ("x = %d\t y = %d\tz = %d\n", x, y, z);
//op : x = 0 y = -1 z = 0
//why are 'x' and 'z' incremented?
it is evaluated as (x && y) || z
x is evaluated and it is false (0)
z is then evaluated and it is false(0)
the result of this condition is actually false.
I may be completely wrong but's how I understand this.
Hope it helps..

Resources