Home > Net >  What is the difference between x =x and x = x y in C
What is the difference between x =x and x = x y in C

Time:10-08

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

-------------------------------------

CodePudding user response:

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.

CodePudding user response:

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:

  1. Evaluate right side to 1.
  2. Evaluate left side:
    1. Set i: 5->6
    2. Return ref to i which holds 6.
  3. 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
  1. Evaluate right side:
    1. Set i: 5->6
    2. Return ref to i which holds 6 now.
    3. Add 1 -> right side is 7.
  2. Evaluate left side:
    1. Set i: 6->7.
    2. Return ref to i which holds 7 now.
  3. 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.

  • Related