Could anyone please explain how these expressions are evaluated?
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a = 1;
a = a++ + a++;
cout<<a<<endl;
a = 1;
a = ++a + ++a;
cout<<a<<endl;
a = 1;
a = a++ + ++a;
cout<<a<<endl;
a = 1;
a = ++a + a++;
cout<<a<<endl;
return 0;
}
OUTPUT:
3
6
4
5
In short: don't. Don't write such code, it's undefined behavior.
Perhaps the easiest way to understand the idea is 'sequence points'. Sequence points split the code into parts which all get evaluated one by one in a well-specified order. For example, in
x++, x *= 2
,,
is a sequence point so firstx++
gets evaluated and thenx *= 2
. Same with&&
and||
operators: first the left side gets executed, then the right one (if needed).On the other hand,
+
does not specify a sequence point, so the standard doesn't say if the left side should be run first or the right side. So when you doa++ + ++a
, the compiler doesn't understand what order you want: do you wanta++
to modifya
and then use its value to evaluate++a
, or the other way round? Because of this uncertainity, such code is considered invalid, which the standard does by saying 'this code has undefined behavior'. The compiler is allowed to do anything when it encounters undefined behavior. When I say anything, I mean really anything, it can crash, format your hard drive, cause a nuclear explosion or whatever it can do.Another nice example of undefined behavior is
i = ++i + 1
. The standard doesn't say that=
is a sequence point. And you modifyi
on both sides of assignment: on the lefti =
is an assignment, on the right++i
is a pre-increment (i.e. assignment), so it's UB.This changed a bit in C++11. In C++11 and later, there are no sequence points anymore, but there are sequence relations which are similar to points. (If you don't dive into details, sequence points always specify 1-2-3-4... order and sequence relations denote a DAG and the compiler may choose any topological sort order it likes, if there are different variants.) Starting with C++11, the second example is no longer UB, because there's a relation that assignment is performed after both sides are evaluated, so first
++i + 1
is evaluated and theni =
is done. It doesn't mean that you should write such code in production, though.