0
int main() {
    int a = 0;
    if(a++ == a){
        std::cout << "A" << std::endl;
    }
    int b = 0;
    if(++b == b){
        std::cout << "B" << std::endl;
    }
}

Output:

B

I was expecting the result to be A since my assumption was that value of a wiil be used before a is incremented since it is post-increment.

Vivek
  • 448
  • 2
  • 11

3 Answers3

5

Both your if conditions have undefined behavior, since you are modifying and accessing a variable in the same expression.

The program could print A, B, AB, nothing, or the program could crash your computer. Absolutely anything can happen when your program has undefined behavior.

Make it a habit to compile programs with warnings enabled, e.g. -Wall, and then the compiler will warn you that you are doing something wrong.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • Thanks. I missed the second rule for undefined behavior in [cppreference](https://en.cppreference.com/w/cpp/language/eval_order). `Sequenced-before rules (since C++11) > Undefined behavior > 2)` If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined. – Vivek Jun 04 '20 at 02:05
1

@cigien answer is correct but I'd like to add detail to it.

When you do if(a++ == a), the left side evaluates to a before increment. That is clear. But what is not so clear is: does the left or right side of == gets evaluated first?

If it is the left side first, then a will be evaluated, then incremented, for the left side. Then a will be evaluated again (+1) so the two expressions won't be equal.

If it is the right side first, then a will be evaluated, for the left side. Then a will be evaluated again (same value), then incremented so the two expressions will be equal.

Similarly, when you pre-increment, if the left side evaluates first, then both will see incremented b, hence false. But if the right side evaluates first, then only the left side will see the incremented b, hence false.

HTH.

Jeffrey
  • 11,063
  • 1
  • 21
  • 42
  • "does the left or right side of == gets evaluated first?" --> or at (nearly) the same time in parallel is a possibility. IAC --> UB. – chux - Reinstate Monica Jun 04 '20 at 02:04
  • yeah, saw your similar comment on the other sequence point question. TBH, I'm doubtful. Why would the compiler emit assembly that can be parallelized for this? Or, how could? Would you have an example from a real world compiler ? My gut feel is that this would run afoul of a bunch of rules, for example aliasing rules. – Jeffrey Jun 04 '20 at 02:34
0

Intuitively, I would say: first, a is returned (for the left side of ==), then it is incremented, then the right side is evaluated with the new value of a (which is bigger than the old value). In the B case, the new value of B is the result on both sides of the equality operator.

Generally, I think this behavior is undefined, which means that the compiler can choose to do whatever: increment a first, not increment a first, launch nuclear missiles at North Korea - read this blog post: https://blog.regehr.org/archives/213

Luka Govedič
  • 399
  • 4
  • 14