0

the output of the code below are different between g++ and clang++ ! I think clang++ is correct, what do you think?

g++ output: 11 4 13 7

clang++ output: 11 4 11 8

#include <iostream>
struct A
{ 
    int a; 
    A(int x): a{x}{}
    A  operator ++(int){ A temp = *this; ++a; return temp; }
    A& operator *(int x){ a*=x; return *this; }
    A& operator +(A& x){ a+=x.a; return *this; }
    operator int(){ return a; }
};
int main() 
{
    int myINT{3};
    int y = myINT++ + myINT * 2;
    std::cout << y << " " << myINT << '\n';

    A myA{3};
    y = myA++ + myA * 2;
    std::cout << y << " " << myA << '\n';

    return 0;
}
Jakob Stark
  • 3,346
  • 6
  • 22
  • 2
    It is undefined behavior to use the increment operator in such an expression. Clang should give you a warning about the "unsequenced modification and access to myInt" ([see live on godbolt](https://godbolt.org/z/1ra34j6a7)). – Jakob Stark Nov 14 '22 at 08:43
  • 3
    What is amazing is that why so many new programmers would want to do anything like this: `y = myA++ + myA * 2;`. Even if this had defined behavior, why have such a confusing line of code written in this fashion? The days of trying to stuff `++` and `+` on one line of code, just to "outdo the compiler's optimizer" are long gone. – PaulMcKenzie Nov 14 '22 at 08:45
  • Both are correct! You only know that the operator ++ is applied to `myInt` (id. for `myA`) after taking its value **in `myInt++`**, but whether it happens before or after taking the value of the other `myInt` operand is not specified by the language. – Serge Ballesta Nov 14 '22 at 08:47
  • 1
    Precedence is not the issue. Precedence does say, for example, that `myINT++` and `myINT *2` are evaluated before their results are added together, but precedence does not go further into which gets evaluated first, or even that one must be fully evaluated before the other. – JaMiT Nov 14 '22 at 08:47
  • 3
    It is not a compiler bug. It is never a compiler bug. – n. m. could be an AI Nov 14 '22 at 08:48
  • Also, g++ and clang are well-established compilers. There is no chance that they have a "bug" in such tiny, simple code. If they had such a bug in a toy program like this, thousands of programmers and companies would have reported it. Thus always assume your program is going into undefined behavior land. – PaulMcKenzie Nov 14 '22 at 08:49
  • jakob stark, clang did gave warning but ran fine and i expected the result, but i did not expect what g++ did: myA *2 did first, now myA = 6, myA++: A::temp =6, myA=7, y =13 – Ammar Tamimi Nov 14 '22 at 08:51
  • 3
    @AmmarTamimi *but i did not expect what g++ did* -- I bought a rope that the manufacturer says can only hold 500 pounds. I put 600 pounds on the rope, and it didn't break. I bought another rope that can hold only 500 pounds, but it broke immediately when I tried to hold up 600 pounds. Who is at fault, the rope, or you for not following the instructions and warnings? – PaulMcKenzie Nov 14 '22 at 08:53
  • @AmmarTamimi It is your expectations that are wrong, not the compilers. Why do you think that what you expect must be right? – john Nov 14 '22 at 08:55
  • @AmmarTamimi by the way GCC also gives you a warning if you enable warnings with the `-Wall` flag (which you really should do). – Jakob Stark Nov 14 '22 at 08:55
  • what I see is inconsistent behavior of g++ part between the two expression: y = myINT++ + myINT*2; and y = myA++ + myA*2; – Ammar Tamimi Nov 14 '22 at 09:05
  • 1
    To be a bit picky, the `int` code has undefined behaviour; the behaviour of the `A` code is not undefined, but its result is unspecified and depends on the order of evaluation of `myA++` and `myA`. – molbdnilo Nov 14 '22 at 09:07
  • 1
    On a side note, mutating `*` and `+` operators are Evil. Just don't. – molbdnilo Nov 14 '22 at 09:16
  • @AmmarTamimi Also, running your program on Visual C++ 2019, the output is `9 4 13 7`. Now you have 3 different compilers and 3 different results. – PaulMcKenzie Nov 14 '22 at 09:17
  • Please don't define `*` and `+` as if they were `*=` and `+=`. – Ranoiaetep Nov 14 '22 at 09:21
  • Please note that _"...undefined behavior - there are no restrictions on the behavior of the program..."_ _"...Compilers are __not__ required to diagnose undefined behavior..."_ https://en.cppreference.com/w/cpp/language/ub The requirement is on the programmer to know the rules of C++, which is kind of tough. IIRC someone did a review of the Standard and came up with nearly 100 cases where UB is explicitly mentioned. – Richard Critten Nov 14 '22 at 09:57
  • I thought unary operator has higher precedence such as myA++, over binary operator such as myA* 2, so myA++ goes first in expression left to right?! – Ammar Tamimi Nov 14 '22 at 10:13
  • @AmmarTamimi Why are you still trying to figure out "unspecified behavior"? I mentioned that Visual C++ gives another set of answers. I wouldn't be the least bit surprised if differing compiler settings yielded different results on the same compiler. – PaulMcKenzie Nov 14 '22 at 14:02
  • @AmmarTamimi *so myA++ goes first in expression left to right?!* -- The compiler is free to evaluate either side of the `+` first -- the order is unspecified. – PaulMcKenzie Nov 14 '22 at 14:15
  • 1
    Operator precedence has nothing to do with what gets executed first. Operator precedence is about which operators get which operands. – n. m. could be an AI Nov 14 '22 at 14:46

0 Answers0