2

I am not able to understand, why the output of the code is not what I was expecting.

#include <iostream>
using namespace std;
int main()
{
    int m = 2, n = 6;
    int &x = m;
    int &y = n;
    m = x++; 
    x = m++;
    n = y++;
    y = n++;
    cout<< m << " " << n; 
    return 0; 
}

I was expecting 4 8

cigien
  • 57,834
  • 11
  • 73
  • 112
Aarsh
  • 370
  • 1
  • 3
  • 13
  • 2
    It sounds like you may need to learn how to use a debugger to step through your code. With a good debugger, you can execute your program line by line and see where it is deviating from what you expect. This is an essential tool if you are going to do any programming. Further reading: [How to debug small programs](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/) and [Debugging Guide](http://idownvotedbecau.se/nodebugging/) – NathanOliver Sep 25 '20 at 12:22
  • since `x` is reference to `m` this line `m = x++;` is same as `m = m++;` and this is undefined behavior. – Marek R Sep 25 '20 at 12:23
  • 2
    @MarekR Not from c++17, I think. – cigien Sep 25 '20 at 12:24
  • Clangs undefined behavior sanitizer doesn't finds anything https://godbolt.org/z/o9a1rv – Marek R Sep 25 '20 at 12:29
  • MSVC gives different answer https://rextester.com/GJWG22689 – Marek R Sep 25 '20 at 12:36
  • You should get together with [Rahul Singh](https://stackoverflow.com/users/13559533/rahul-singh) as you both are working on the [same issue](https://stackoverflow.com/questions/64068344/explain-me-to-understand-the-output-of-following-code). – Thomas Matthews Sep 25 '20 at 17:04

2 Answers2

6

This line:

m = x++; 

is equivalent to:

x = x++;

since m is a reference to x.

From c++17, the right hand side is evaluated first, resulting in 2. Then x is incremented to 3. Then the assignment of the right hand side value to the left hand side is done. But this uses the old value of the right hand side, which is 2. So the above statement effectively does nothing.

Before c++17,

m = x++;

is undefined behavior.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • Checking my knowledge here: Before C++17 was it undefined because assignment and increment were both sequenced after return, but not sequenced against each others? – Frodyne Sep 25 '20 at 12:37
  • @Frodyne Pretty much. Here's a useful [answer](https://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) that covers this in detail. – cigien Sep 25 '20 at 12:40
  • I've run this code using msvc on my machine and with switch `/std:c++14` it produces `4 8` and for `/std:c++17` it produces result `2 6`. – Marek R Sep 25 '20 at 12:40
  • @MarekR For c++17, I explained the result in the answer. Pre c++17 it's UB so don't worry about it :) – cigien Sep 25 '20 at 12:43
  • 1
    @cigien I know, this was just experimental proof. Anyway IMO this should fail during build (it is C++14 constexpr with UB): https://godbolt.org/z/7fsTMG. – Marek R Sep 25 '20 at 12:47
  • @MarekR That's a good point. Seems like a reasonable question to ask :) If you don't, and I can't find an answer on SO, I'll ask it myself. – cigien Sep 25 '20 at 12:49
  • What is funny when I running https://godbolt.org/z/7fsTMG on my machine with msvc (19.25.28614) I got answer `2 8`, but when I just remove last `constexpr` from it it produces answer `4 8` (same build options). – Marek R Sep 25 '20 at 13:17
  • I don't understand what you're confused by. Of course UB could end up showing different results (it could do that every time you run the same program). The only interesting thing here is why `constexpr` doesn't diagnose it. – cigien Sep 25 '20 at 13:20
  • 1
    `constexpr` should be UB free. Compiler should file an error in case UB is present in `constexpr`. So this is bug in msvc for sure. – Marek R Sep 25 '20 at 13:29
1

Notice how the operators are post-increment and not pre-increment... You're basically doing nothing.

m = x++; means that increment x (i.e. m) but return the old value of x (i.e. m). Assignment takes place after the increment and return of old value and the old value is what ends up getting assigned. So, you end up essentially with a bunch of self-assignments.

Arrow
  • 389
  • 2
  • 12