int main() {
int x = 6;
x = x+2, ++x, x-4, ++x, x+5;
std::cout << x;
}
// Output: 10
int main() {
int x = 6;
x = (x+2, ++x, x-4, ++x, x+5);
std::cout << x;
}
// Output: 13
Please explain.
Because , has lower precedence than =. In fact, , has the lowest precedence of all operators.
First case:
x=x+2,++x,x-4,++x,x+5;
This is equivalent to
(x=x+2),(++x),(x-4),(++x),(x+5);
So, x becomes 6+2 = 8, then it is incremented and becomes 9. The next expression is a no-op, that is x-4 value is calculated and discarded, then increment again, now x is 10, and finally, another no-op. x is 10.
Second case:
x=(x+2,++x,x-4,++x,x+5);
This is equivalent to
x=((x+2),(++x),(x-4),(++x),(x+5));
x+2 is calculated, then x is incremented and becomes 7, then x - 4 is calculated, then x is incremented again and becomes 8, and finally x+5 is calculated which is 13. This operand, being the rightmost one, is the taken as the result of the whole comma expression. This value is assigned to x. x is 13.
Hope it's clear.
And, as one of the comments suggests - NEVER WRITE CODE LIKE THIS
Related
I don't understand why my two expressions produce the same result even though the second expression calls f() twice.
I am using gcc with C++20 enabled.
#include <iostream>
using namespace std;
int& f(int& i, string name);
int main() {
puts("\n-------------------------------------\n");
int x = 5;
/* expression one */
printf("the result of (f(x) += 1) is:--> %d\n", f(x, "one") += 1);
printf("x is: %d\n",x);
printf("********************\n");
x = 5;
/* expression two */
printf("the result is:--> %d\n", f(x, "two") = f(x, "three") + 1);
printf("x is: %d\n", x);
puts("\n-------------------------------------\n");
return EXIT_SUCCESS;
}
int& f(int& i, string name) {
++i;
printf("<%s> value of i is: %d\n", name.c_str(), i);
return i;
}
The output of my program is:
-------------------------------------
<one> value of i is: 6
the result of (f(x) += 1) is:--> 7
x is: 7
********************
<three> value of i is: 6
<two> value of i is: 7
the result is:--> 7
x is: 7
-------------------------------------
If we break expression 2 into separate steps it might become clearer what is happening:
f(x, "two") = f(x, "three") + 1;
Is equivalent to (though note the order of evaluation isn't guaranteed before c++17):
int b = f(x, "three") + 1;
int& a = f(x, "two");
a = b;
However as f(x) returns a reference to x, a is also a reference to x. Using this if we then expand the function calls we get:
int b = ++x + 1;
++x;
x = b;
Notice how the second ++x is ignored, this is why it doesn't have the value you expect.
Note that this is undefined behaviour before (and correct after) C++17 which explicitly sequences evaluation of left, right sides including their side-effects.
f(x, "one") += 1
is evaluated as:
Evaluate right side to 1.
Evaluate left side:
Set i: 5->6
Return ref to i which holds 6.
Evaluate += by adding one to the returned reference, setting i: 6->7.
The expression is evaluated to ref to i holding 7.
f(x, "two") = f(x, "three") + 1
Evaluate right side:
Set i: 5->6
Return ref to i which holds 6 now.
Add 1 -> right side is 7.
Evaluate left side:
Set i: 6->7.
Return ref to i which holds 7 now.
Evaluate = by assigning the right side(7) to left side(i), setting i to 7.
The expression is evaluated to ref to i holding 7.
In the second expression it doesn't matter what happens to i inside left f call - if it returns i ref, it will be set to 7.
I used greater than and less than signs and it gives ouput! How it is working ?
int x = 2;
x >= 3;
cout << x; // output is 2
And also the output is different like this
int x = 2;
x = x > 3;
cout << x; // output is zero !! HOW ??
The expression
x >= 3
is a pure comparison. It tests, whether the value of variable x is greater than, or equals 3. The result is 0 or 1 – for x equal 2 it is zero, false.
Terminating the expression with a semicolon creates a statement. That statement performs a comparison and ...nothing else. The result of comparison is discarded, and the variable x remains unchanged. Hence the observed resulting value 2.
In x = x > 3; the subexpression x > 3 is a comparison. Its result is 1 if the comparison succeedes, 0 otherwise.
Since you initialized x to 2, the result of the comparison is false, i.e. zero.
As a result
x = x > 3;
equivalent to
x = (x > 3);
resolves to
x = 0;
hence the output you observed.
If you use
int x = 2;
x >= 3;
cout << x;
the output is 2 because the result of the x >= 3 operation is discarded (not used) and x remains by the same value as it were initialized. x was not assigned by any value after its initialization.
If you use
int x = 2;
x = x > 3;
cout << x; `
x is checked whether it is greater than 3 or not with x > 3. If it is, the value of the expression x > 3 turns 1, if not it turns 0. Comparison operations are boolean expressions.
This boolean value is assigned back to x after the evaluation of x > 3.
Since x is not greater than 3, the expression x > 3 gains the value 0 and this value is assigned back to x and finally what is printed.
i have a little problem with this small piece of code;
If i use the ++ operation (x++) it works fine, but if i write "x + 1" it breaks and causes an infinite loop of zeros.
The code:
int x = 0;
while (x <= 20)
{
std::cout << x << std::endl;
x + 1;
}
Any help would be appreciated!
If you want to set a value of a variable you must* use an =.
This : x + 1 is NOT the same as x = x + 1 or x += 1 or x++.
When you add that x plus to your code you are never changing the value of x.
x + 1 simply returns a temporary value of the result. Where as the other three listed about will change the value of x instead of creating a temporary value.
You need to know the differences between different statements related to increment as below.
x++ means x = x + 1; which means copy the value of x into temporary
register, increment the value by 1 and write that register value back
into x.
x + 1 means, copy the value of x into temporary register, increment
the value by 1. You are not assigning the value back to x. So x value
won't be changed.
So in your while loop, x value is not being changed which is reason for infinite loop.
This (note the comma operator):
#include <iostream>
int main() {
int x;
x = 2, 3;
std::cout << x << "\n";
return 0;
}
outputs 2.
However, if you use return with the comma operator, this:
#include <iostream>
int f() { return 2, 3; }
int main() {
int x;
x = f();
std::cout << x << "\n";
return 0;
}
outputs 3.
Why is the comma operator behaving differently with return?
According to the Operator Precedence, comma operator has lower precedence than operator=, so x = 2,3; is equivalent to (x = 2),3;. (Operator precedence determines how operator will be bound to its arguments, tighter or looser than other operators according to their precedences.)
Note the comma expression is (x = 2),3 here, not 2,3. x = 2 is evaluated at first (and its side effects are completed), then the result is discarded, then 3 is evaluated (it does nothing in fact). That's why the value of x is 2. Note that 3 is the result of the whole comma expression (i.e. x = 2,3), it won't be used to assign to x. (Change it to x = (2,3);, x will be assigned with 3.)
For return 2,3;, the comma expression is 2,3, 2 is evaluated then its result is discarded, and then 3 is evaluated and returned as the result of the whole comma expression, which is returned by the return statement later.
Additional informations about Expressions and Statements
An expression is a sequence of operators and their operands, that specifies a computation.
x = 2,3; is expression statement, x = 2,3 is the expression here.
An expression followed by a semicolon is a statement.
Syntax: attr(optional) expression(optional) ; (1)
return 2,3; is jump statement (return statement), 2,3 is the expression here.
Syntax: attr(optional) return expression(optional) ; (1)
The comma (also known as the expression separation) operator is evaluated from left to right. So return 2,3; is equivalent to return 3;.
The evaluation of x = 2,3; is (x = 2), 3; due to operator precedence. Evaluation is still from left to right, and the entire expression has the value 3 with the side-effect of x assuming the value of 2.
This statement:
x = 2,3;
is composed by two expressions:
> x = 2
> 3
Since operator precedence,
= has more precedence than comma ,, so x = 2 is evaluated and after 3. Then x will be equal to 2.
In the return instead:
int f(){ return 2,3; }
The language syntax is :
return <expression>
Note return is not part of expression.
So in that case the two expression will be evaluated will be:
> 2
> 3
But only the second (3) will be returned.
Try to apply the simplistic approach just highlighting the precedence with parenthesis:
( x = 2 ), 3;
return ( 2, 3 );
Now we can see the binary operator "," working in the same way on both, from left to right.
This question already has answers here:
Post increment and Pre increment in C
(3 answers)
Closed 9 years ago.
I was expecting this code snippet to print 3 as the if condition is false and y++ will execute, but it prints 2, any idea why..Thanks!!
int x = 3;
int y = 2;
printf("%d\n", (x<y) ? x++ : y++);
// This prints 2
x++ and y++ are post-increment. That is, they return the current value of the variable, then add one to it.
Pre-increment would be ++x or ++y. Those increment and then return the new value.
Both pre- and post-increment (and -decrement) are useful things when writing loop controls, which is why C supports both.
(Originally, if I remember correctly, C only supported pre-increment and post-decrement, because there happened to be instructions on the machines it was developed on which encapsulated those behaviors. But as C moved to other systems, and as people started noticing that they wanted both pre and post for both, this was generalized.)
Note that this means the c++ language was misnamed. It should have been called ++c -- we want it improved before we use it, not after!
It's because y++ returns the value of y then increases it.
Where as if you put ++y it would increase the value of y first then return it.
The ++ operators are evaluated last; this is called "post-increment." So, this:
int x = 3;
int y = 2;
printf("%d\n", (x<y) ? x++ : y++);
is equivalent to this:
int x = 3;
int y = 2;
printf("%d\n", (x<y) ? x : y);
y++;
(x++ isn't ever reached because of the ternary condition.) On the other hand, this:
int x = 3;
int y = 2;
printf("%d\n", (x<y) ? ++x : ++y);
would increment y before returning its respective value to printf(), so the logic would be:
printf("%d\n", (3<2) ? 3 : 3); // prints 3
Since you use a post increment y++, value of y will be used first and incremented. That is the printf will be passed the value before increment operation, in your case y is 2 before increment and 2 will be printed.
You should consider x++ and y++ after all the other operations of this line have been completed. So, print y and then increment x and y.