Reputation: 305
When I execute the following code
#include <iostream>
int & f(int &i)
{
puts("this is f");
return ++i;
}
int main()
{
int x = 5;
printf("%d", f(x) = f(x) + 1);
return 0;
}
I get output as 8. I am unable to understand how that's happening. Can anyone give me a reason for that?
Upvotes: 0
Views: 106
Reputation: 1246
Look how this line of code is evaluated:
printf("%d",f(x)=f(x)+1);
Step 1: Initialization of x --> x == 5
Step 2: First call of f (right side of equals sign) --> x == 6
Step 3: Adding 1 --> x == 7
Step 4: Second call of f (left side of equals sign) --> x == 8
EDIT(see comment for deeper insight & thx to Matt):
Upvotes: 2
Reputation: 141554
It's unspecified which of the two calls to f(x)
occurs first; and if the right-hand-side one was called first, it's unspecified whether the prvalue conversion of that occurs before or after the call to the left-hand-side's f(x)
. But all of those happen before the assignment.
One valid order is:
which results in i = 7 + 1;
.
Alternatively it could be:
which results in i = 6 + 1;
There is no undefined behaviour relating to the ++
operator, because there is a sequence-point before and after each function call.
Refs: [intro.execution]#15
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced
[expr.ass]#1
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.
In this quote, "the value computation of the assignment expression" means the value that this expression takes if it's a sub-expression of a larger expression, e.g. bar = ( foo(x) = foo(x) + 1 );
This code will let you inspect which order your compiler is using. I have inserted bar
which passes its value through unmodified.
#include <cstdio>
using namespace std;
int & f(int idx, int &i)
{
printf("this is f %s\n", idx ? "right" : "left");
return ++i;
}
int bar(int idx, int z)
{
printf("bar%d = %d\n", idx, z);
return z;
}
int main()
{
int x=5;
f(0,x)= bar(0, bar(1, f(1,x)) + 1 );
printf("final = %d\n",x);
return 0;
}
Output for my system:
this is f left
this is f right
bar1 = 7
bar0 = 8
final = 8
Output for Coliru:
this is f right
bar1 = 6
bar0 = 7
this is f left
final = 7
Upvotes: 2
Reputation: 867
#include <iostream>
int & f(int &i)
{
puts("this is f");
return ++i;
}
int main()
{
int x=5;
//f(x)=f(x)+1 equals to following
int& tmp_x = f(x); //x=6
int tmp = f(x)+1; //x = 7, tmp = 8
tmp_x = tmp; //x=8
printf("%d",tmp_x);
return 0;
}
Upvotes: 0
Reputation: 1258
You use reference parameter. When you modify the variable x in the f function, you modify too in main function.
First x = 5
When you call f first time, x = 6
When you call f second time, x = 7
Finally, 7 + 1 = 8
Upvotes: 1
Reputation: 2435
Function parameter i
is a reference to int x
.
So, ++i
is actually incrementing x
.
f(x)
is called twice with initial x=5
which will make x
equal to 7.
But 1 is added at printf
, making final value printed 8.
Upvotes: 0