Sparrow
Sparrow

Reputation: 305

Compound operation evaluation in C++

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

Answers (5)

PrR3
PrR3

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

M.M
M.M

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:

  • lhs f(x)
  • rhs f(x)
  • rvalue conversion

which results in i = 7 + 1;.

Alternatively it could be:

  • rhs f(x)
  • rvalue conversion
  • lhs f(x)

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

RSATom
RSATom

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

MiguelAngel_LV
MiguelAngel_LV

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

Keugyeol
Keugyeol

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

Related Questions