r/cpp•
chillhelm

[Showerthought] c>c++ is actually true.

int main(int,char*[]) {
    int c=0;
    if(c>c++)
        std::cout << "Ooops UB!" <<std::endl;
    return 1;
}

So much for c++ being bigger than c.

Petition to rename c++ to ++c.

Edit: It has been pointed out to me that this is UB based on the order of evaluation rules. However, I'll leave the post so others can learn from my shame. (Thank you to u/HappyFruitTree and u/TheSuperWig)

Posted Oct 7, 2020, 10:47 AM UTC · edited

017
HappyFruitTree•

It's undefined behaviour.

25
chillhelmOP•

Is it? Based on what rule?

1
HappyFruitTree•

The sequenced-before rules (C++11 or later) or the sequence point rules (before C++11).

18
chillhelmOP•

Ah well. You are right. The Standard Comittee has beaten me again.

8
staletic•

I like the "Ooops UB!" edit.

3
TheSuperWig•

This is undefined behaviour

https://godbolt.org/z/a7Pxcj

12
Ail-nare•

I'm 100% sure that c>c++ == false

2
chillhelmOP•
2
evaned•

Now try it with Clang, there slightly modified to be more explicit.

Also note the -w I "needed" to get Clang to not warn about the conditional.

3
nollib101•

0>0? Should be false, I don't know I'm not a mathematician

1
Tranzistors•

Depends evaluation order. If the right hand side is evaluated first, then the expression c>c++ turns into 1>0. In math even x=1;x=2; is absurd, let alone x++.

8
chillhelmOP•

Well both sides have to be evaluated before operator> is called, so evaluation order doesn't matter here.

-3
evaned•

The reason that it's UB is that it does matter. Both sides of the > have to be evaluated, but what order that happens in is unspecified. For example, foo() > bar() could cause either function to be called first. (I think this is still true? C++17 messed with some of these rules.) All what you said means is that both functions need to be called before > can be evaluated, of course.

So setting aside the sequence point violation that makes it outright UB and not just unspecified, c > c++ could be evaluated as either c > c++ => 0 > c++ => 0 > 0 (and now c==1) => false or as c > c=++ => c > 0 (and now c==1) => 1 > 0 => true.

4
mallardtheduck•

I believe this is UB (and GCC agrees when -Wsequence-point is enabled), therefore the compiler is free to do whatever it likes.

2
chillhelmOP•

The value of c++ is 0 (since it's the post-increment operator). But since c has been incremented when the right side of operator> is evaluated c is one. So operator> gets two ints as input, namely a copy of c for the left (which has value 1) and a copy of the temporary that is the return value of the expression c++ which has value 0. Therefor the expression checks that 1>0 which indeed evaluates to true.

-2†