3

In Python, you can easily exchange the values of 2 variables with an expression like this:

x, y = y, x

In C++, on the other hand, if you want to exchange the values of 2 variables, you usually use a temporary variable to store the value of one of your variables, something like this:

int var1 = 100;
int var2 = 200;

int temp = var1;
var1 = var2;
var2 = temp;

This is easy, but you have to write a lot of code.

A professor that I have been following for his lectures on C++ has discovered a new compact way of exchange the values of 2 variables in a magic way:

int x = 200;
int y = 100;

x = y - x + (y = x);

It seems incredible, but it works both with the compiler he's using and mine Apple LLVM version 6.0 (clang-600.0.56).

It seems that the way that expression is interpreted is the following:

  1. (y = x) // returns the value of x
  2. -x + x = 0
  3. x = y + 0
  4. x = y
  5. y = x // finally, y receives the initial value of x

If I try to exchange the values of some variables in a loop, it seems also to work:

for (int i = -10; i <= 10; i++) {
    for (int j = 10; j >= -10; j--) {
        int x = i, y = j;
        x = y - x + (y = x);

        std::cout << "x = " << x << "\ny = " << y << '\n';
    }
}

We have seen that the exchange is done, but my compiler gives me this warning:

main.cpp:28:22: warning: unsequenced modification and access to 'y' [-Wunsequenced]

If there's a warning, I suppose this is not a new standard way of exchanging the values of 2 variables, but was just an ingenious workaround of this professor.

Why this method is not standardised in C++, and why exactly does it work?

nbro
  • 15,395
  • 32
  • 113
  • 196

3 Answers3

10

This is undefined behavior, and it's not guaranteed to work. The order of evaluation of the parameters in an expression is not specified. So it's allowed to access the value of y for the subtraction before or after it performs the y = x assignment.

The reason it's specified like this is to allow flexibility for optimizations.

Barmar
  • 741,623
  • 53
  • 500
  • 612
6

It "works" because you were unlucky.

Yes, I said unlucky. The code has undefined behavior; the fact that it appears to "work" means that your compiler has let you get away with code that could fail next time you run it.

x = y - x + (y = x);

The object y is accessed twice, once to read its value and once to assign a value to it. The language does not define the order in which those accesses occur -- or that the occur in any order at all. As the warning message says, they're "unsequenced". The possible behaviors are not limited to the two possible orders; the behavior is entirely undefined.

Furthermore, the addition and/or subtraction could overflow, which is another potential source of undefined behavior.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
2

This, `x = y - x + (y = x);, is undefined behavior in C - one undefined behavior listed by the C99 spec is:

Between two sequence points, an object is modified more than once, or is modified and the prior value is read other than to determine the value to be stored

The only sequence points in this expression are the beginning of the expression and the end of the complete expression.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760