given that
int w = 1;
int x = 6;
int y = 5;
int z = 0;
z = !z || !x && !y;
printf("%d\n", z);
z = x-- == y + 1;
printf("%d\n", z);
Could someone explain how the line below would evaluate to 1 if x-- is 5 and y+1 is 6?
z = x-- == y + 1;
The expression x-- evaluated to the value of x before being decremented.
So x-- == y + 1 is the same as 6 == 5 + 1 which is true, then the value 1 is assigned to z.
The expression
z = x-- == y + 1
will be parsed as
z = ((x--) == (y + 1))
IOW, you are comparing the result of x-- to the result of y + 1, and assigning the result of that comparison to z.
The result of x-- is the current value of x; the side effect is that x is decremented. So, given
x == 6
y == 5
then
x-- == 6
y + 1 == 6
(x-- == y + 1) == 1
so 1 is assigned to z; after this evaluation, x will equal 5.
Note that C does not force left-to-right evaluation in this case - y + 1 may be evaluated before x--. Also be aware that the side effect of the -- operator on x does not have to be applied immediately after evaluation - the whole thing could be evaluated as
t1 <- y + 1
t2 <- x
z <- t2 == t1
x <- x - 1
or
t1 <- x
t2 <- y + 1
x <- x - 1
z <- t1 == t2
or any other order. The update to x and the assignment to z can happen in any order, even simultaneously (either interleaved or in parallel).
While idiomatic C is often a little head-scratchy, this takes things a bit too far. As an academic exercise for learning about operator precedence and side effects it's okay (not great), but anyone who did this in production code could expect some grief over it in a code review. If nothing else it doesn't scan well - just adding some parens (like I did above) would greatly help with readability.
From the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the operand.
As a side effect, the value of the operand object is incremented (that
is, the value 1 of the appropriate type is added to it).
3 The postfix -- operator is analogous to the postfix ++ operator,
except that the value of the operand is decremented (that is, the
value 1 of the appropriate type is subtracted from it)
Thus in this expression statement
z = x-- == y + 1;
that may be equivalently rewritten like
z = ( x-- ) == ( y + 1 );
the value of the postfix decrement expression x-- is the value of the variable x before decrementing. That is the value of the expression is equal to 6.
The value of the expression y + 1 is also equal to 6 because the value of y is equal to 5.
And at last (the C Standard, 6.5.9 Equality operators)
3 The == (equal to) and != (not equal to) operators are analogous to
the relational operators except for their lower precedence.108) Each
of the operators yields 1 if the specified relation is true and 0 if
it is false. The result has type int. For any pair of operands,
exactly one of the relations is true
So as the value of the expression x-- is equal to the value of the expression y + 1 then the variable z gets the value 1.
You could get the expected by you result keeping the postfix decrement operator the following way
z = ( x--, x == y + 1 );
by inserting the comma operator. In this case after the comma operator there is a sequence point that means that in second operand of the comma operator x == y + 1 x will be already equal to 5.
On the other hand, if you will write for example the expression like this
z = --x == y + 1;
where instead of the postfix decrement operator there is used unary decrement operator -- then the value of the expression --x will be equal to 5 (the value of the unary decrement operator is the value of its operand after decrementing). In this case the variable z gets the value 0 because 5 is not equal to 6 (the value of the expression y + 1).
Related
I have to analyze what some code in C does, and I have a doubt about what happens in a certain line. The code is
#define PRINTX printf("%d\n", x)
void problem() {
int x = 2, y, z;
x *= 3 + 2; PRINTX;
x *= y = z = 4; PRINTX;
x = y == z; PRINTX;
x == (y = z); PRINTX; // This line is the problem
}
This code snippet prints the resulting numbers:
10
40
1
1 // This result **
the problem is that I'm still trying to figure out why does the last line prints out x = 1, when the operation is x == (y = z). I'm having trouble finding out what that 1 means and the precedence of the operations. Hope someone can help me! :)
Nothing in the last statement changes the value of x, so its value remains unchanged.
Parens were used to override precedence, forcing the = to be the operand of the ==.
An operator's operands must necessarily be evaluated before the operator itself, so we know the following:
y is evaluated at some point before the =.
z is evaluated at some point before the =.
x is evaluated at some point before the ==.
= is evaluated at some point before ==.
That's it. All of these are valid orders:
z y = x ==
y z = x ==
x y z = ==
etc.
But whenever x, y and z are evaluated, we can count on the following happening:
= assigns the value of z (currently 4) to y and returns it.
== compares the value of x (currently 1) with the value returned by = (4). Since they're different, == returns 0 (which isn't used by anything).
As you see, nothing changed x, so it still has the value it previously had (1).
In the last statement, nothing is changing the value of x. We are testing if x equals something, but we aren't changing it's value.
So it continues having the same value as it had in the previous statement, in particular, a value of 1.
the reason is because the == operator checks if the 2 numbers are equal, and returns 1 if equal and 0 if not equal that is why it returns one you can check by making x= 1 and y=2 and using the == operator between them
The comparison result of x and assignment of y with (y = z) is discarded. Last line could have dropped the compare: y = z; PRINTX;.
The assignment is not subsequently used either, so the line could have been PRINTX;.
I'm stuck in a question of decrement the code is as follows
#include <stdio.h>
int main()
{
int x = 4, y = 3, z;
z = x-- - y;
printf("%d %d %d\n",x,y,z);
return 0;
}
according to what i know the output should be 4 3 0
the explanation for the value of z according to me is as follows:
first as it's a post decrement so first we'll decrease the value of y from x i.e. 4-3 that's equal to 1 and according to me we'll again decrease 1 from this 1 (or we don't correct me if I'm wrong here) and the output will be 0.
The expression x-- evaluates to the current value of x which is 4. The value of y is then subtracted from this value resulting in 1 which is what is assigned to z.
x is then decremented as a side effect of the postdecrement.
So the output will be 3 3 1.
From the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the operand.
As a side effect, the value of the operand object is incremented (that
is, the value 1 of the appropriate type is added to it). See the
discussions of additive operators and compound assignment for
information on constraints, types, and conversions and the effects of
operations on pointers. The value computation of the result is
sequenced before the side effect of updating the stored value of the
operand. With respect to an indeterminately-sequenced function call,
the operation of postfix ++ is a single evaluation. Postfix ++ on an
object with atomic type is a read-modify-write operation with
memory_order_seq_cst memory order semantics.98)
3 The postfix -- operator is analogous to the postfix ++ operator,
except that the value of the operand is decremented (that is, the
value 1 of the appropriate type is subtracted from it).
Thus in this statement
z = x-- - y;
there is used the value of the variable x before the decrement that is 4. So 4 - 3 yields 1.
But the object x itself was decremented and after this statement its value becomes equal to 3.
So as result you will get the following output
3 3 1
By the way you may rewrite this statement
z = x-- - y;
like :)
z = x --- y;
This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 5 years ago.
#include <stdio.h>
main()
{
int x = 1, y = 0, z = 5;
int a = x && y || z++;
printf("%d", z);
}
This code gives me output : 6
#include <stdio.h>
main()
{
int x = 1, y = 0, z = 5;
int a = x && y && z++;
printf("%d", z);
}
This code gives me output : 5
Why the second program gives ouput as 5 even though z was incremented same like in first program?
The && operator (as well as the || operator) is a short-circuit operator. That means that if the left operand evaluates false, the result is false regardless of the right operand, so the right operand is not evaluated.
From section 6.5.13 of the C standard:
4 Unlike the bitwise binary & 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 equal to 0, the second operand is not evaluated.
So in the case of this expression:
x && y && z++;
x && y is evaluated first. Since x is 1, y is evaluated and found to be 0, so the result of the first && is 0. Now we have:
0 && z++
Since the left operand is 0, the right operand is not evaluated. This means that z is not incremented.
This is in contrast to expression in the first piece of code:
x && y || z++
As before, x && y evaluates to 0, leaving us with:
0 || z++
Since the left operand is 0, the right operand needs to be evaluated. This results in z getting incremented.
Evaluation of x && y && z++ stops after y because y==0. z++ is not executed.
The initializer in this declaration
int a = x && y || z++;
is equivalent to
int a = ( x && y ) || ( z++ );
According to the C Standard relative to the logical OR operator (6.5.14 Logical OR operator)
4 ... If the first operand compares unequal to 0, the second operand is
not evaluated.
However the first operand that is ( x && y ) compares equal to 0 (due to the variable y is equal to 0). So the second operand ( z++ ) is evaluated.
The initializer in this declaration
int a = x && y && z++;
is equivalent to
int a = ( x && y ) && ( z++ );
According to the C Standard relative to the logical AND operator (6.5.13 Logical AND operator)
4 ...If the first operand compares equal to 0, the second operand is
not evaluated
So as the first operand ( x && y ) compares equal to 0 then the second operand ( z++ ) is not evaluated.
#include<stdio.h>
main()
{
int x = 5, y = 10, z = 10;
x = y == z; // This computational expression causes the value of x to be 1. I fail to understand why
printf("%d\n", x); //Why is the value of x 1 here.
}
I fail to understand the statement x = y ==z;
According to me - x = 10 since y == z. z=10 and is stated to be equivalent to y. The value of y is then assigned to x - x = y
You assign the result of the comparison »Is y equal to z« to x, which is 1, i.e. true.
Note the different operators:
x = ... // assignment
y == z // comparison with either 0 (false) or 1 (true) result
Let's break the program down a little bit further:
You initialize x to 5 and y and z to 10.
You perform a comparison (see above) of y and z without caring for the result. So that's a line that can safely be ignored. But it results in 1 since y is equal to z.
You print the current values of all three variables.
You perform the same comparison, this time assigning the result to x. x now has the value »Is y equal to z«, which is 1 in this case.
Because of operators precedence
x = y == z;
is the same as
x = (y == z);
Now as y == z evaluates to 1, so x value is 1 after the statement.
y == z returns 1 if they are the same and 0 if they are not and the result of this is set to x
== is a comparison operator, so will return 1 (true) if both of the operands are equal and 0 (false) if they are not.
The statement x = y == z is equivalent to x = (y == z), because == has a higher precedence than =. Because y is equal to z, this will assign 1 to x.
Please refer to Operator Precedence Table. == (Comparison Operator) has a higher precedence over = (Assignment Operator). So, the y == z gets executed first and then yields result of 1 as y and z are having the same values which results in x being assigned a value of 1.
= is the assignment operator and == is the comparison operator. you compare y and z, they are equal, so the comparison returns true which is 1. this value is assigned to x.
the == operator acts first.
Hence it becomes x= (value of y==z);
now since y and z are the same, the value of y==z is 1 that gets assigned to x.
== has a greater precedence than =.
The expression y == z is evaluated to 1.
The instruction x = y == z puts 1 in x.
The instruction printf("%d\n", x); prints the value of x (1).
The precedence of == operator is higher than = operator.
y==z evaluates to 1; since both are equal.
Thisn value gets assigned to x.
I have a question about these two C statements:
x = y++;
t = *ptr++;
With statement 1, the initial value of y is copied into x then y is incremented.
With statement 2, We look into the value pointed at by *ptr, putting that into variable t, then sometime later increment ptr.
For statement 1, the suffix increment operator has higher precedence than the assignment operator. So shouldn't y be incremented first and then x is assigned to the incremented value of y?
I'm not understanding operator precedence in these situations.
You're mistaken about the meaning of your 2]. Post-increment always yields the value from before the increment, then sometime afterward increments the value.
Therefore, t = *ptr++ is essentially equivalent to:
t = *ptr;
ptr = ptr + 1;
The same applies with your 1] -- the value yielded from y++ is the value of y before the increment. Precedence doesn't change that -- regardless of how much higher or lower the precedence of other operators in the expression, the value it yields will always be the value from before the increment, and the increment will be done sometime afterwards.
Difference between pre-increment and post-increment in C:
Pre-increment and Post-increment are built-in Unary Operators. Unary means: "A function with ONE input". "Operator" means: "a modification is done to the variable".
The increment (++) and decrement (--) builtin Unary operators modify the variable that they are attached to. If you tried to use these Unary Operators against a constant or a literal, you will get an error.
In C, here is a list of all the Built-in Unary operators:
Increment: ++x, x++
Decrement: −−x, x−−
Address: &x
Indirection: *x
Positive: +x
Negative: −x
Ones_complement: ~x
Logical_negation: !x
Sizeof: sizeof x, sizeof(type-name)
Cast: (type-name) cast-expression
These builtin operators are functions in disguise that take the variable input and place the result of the calculation back out into the same variable.
Example of post-increment:
int x = 0; //variable x receives the value 0.
int y = 5; //variable y receives the value 5
x = y++; //variable x receives the value of y which is 5, then y
//is incremented to 6.
//Now x has the value 5 and y has the value 6.
//the ++ to the right of the variable means do the increment after the statement
Example of pre-increment:
int x = 0; //variable x receives the value 0.
int y = 5; //variable y receives the value 5
x = ++y; //variable y is incremented to 6, then variable x receives
//the value of y which is 6.
//Now x has the value 6 and y has the value 6.
//the ++ to the left of the variable means do the increment before the statement
Example of post-decrement:
int x = 0; //variable x receives the value 0.
int y = 5; //variable y receives the value 5
x = y--; //variable x receives the value of y which is 5, then y
//is decremented to 4.
//Now x has the value 5 and y has the value 4.
//the -- to the right of the variable means do the decrement after the statement
Example of pre-decrement:
int x = 0; //variable x receives the value 0.
int y = 5; //variable y receives the value 5
x = --y; //variable y is decremented to 4, then variable x receives
//the value of y which is 4.
//x has the value 4 and y has the value 4.
//the -- to the right of the variable means do the decrement before the statement
int rm=10,vivek=10;
printf("the preincrement value rm++=%d\n",++rmv);//the value is 11
printf("the postincrement value vivek++=%d",vivek++);//the value is 10