Tricky increment example

Jun 22, 2015 at 12:26pm
Hi guys,

I stumbled upon a tricky increment example recently. Here it is:

1
2
  int a, i = 0;
  a = ++i + ++i + ++i;


Why on earth the a variable returns 9? My logic: increment operation has a higher priority than adding, so the first time i is incremented -- we have 1, the 2nd time -- we have 2, and the 3rd -- 3. Then we have a = 1 + 2 + 3 and which equals 6. Why is it 9?
Jun 22, 2015 at 12:35pm
Standard says it is undefined behavior.
Any conforming implementation can issue a compilation error, runtime error, return 42, explode your computer or do anything else.

Trying to reason about it result is strictly theoretical: actual use of that code in application is the sign of incompetence.


Compiler might do as you says, he can evaluate all increments first and then start reading the value of i for sum operands (most likely in your case), it even can do following:
read i into a
read i into b
increment a
increment b
save a into i
save c into i
read i into b
increment b
save b into i
sum a, b and c

result: sum is 4, i is 2.

So, do not do thing which are prohibited by language rules.
Jun 22, 2015 at 12:56pm
Why is it 9?
Yes, it is undefined what happens.
In this case obviously i is first incremented (-> 3 times) and then added (3+3+3=9)
Jun 22, 2015 at 1:17pm
Checking my copy of Stroustrup, The C++ Programming Language, I see it does not warn about the danger of using operator++ more than once in the same expression (though I don't own the very latest edition.)

The standard states
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.

which is not exactly friendly language.

But it means that your experimental code is invalid as is

++i = 2; // value of i is changed twice

Andy

Further reading for the keen:

Undefined behavior and sequence points
http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points

Undefined behavior and sequence points reloaded
http://stackoverflow.com/questions/4638364/undefined-behavior-and-sequence-points-reloaded
Last edited on Jun 22, 2015 at 1:18pm
Jun 22, 2015 at 1:20pm
But it means that your experimental code is invalid as is

++i = 2; // value of i is changed twice
That code is actually valid. evaluation of all operands (increment) is sequenced-before side effect of operator (actual assigment)
Jun 22, 2015 at 3:34pm
That code is actually valid.

Edit: Ah OK. It's valid C++11 but not before...

I was lazy; this example was lifted from the first stackoverflow thread.

From the above sentence the following expressions invoke Undefined Behaviour.

i++ * ++i; // i is modified more than once
i = ++i    // same as above
++i = 2;   // same as above
i = ++i +1 // same as above
++++++i;   //parsed as (++(++(++i)))


i = (i,++i,++i); // Undefined Behaviour because there's no sequence point between `++i`(right most) and assignment to `i` (`i` gets modified more than once b/w two SP)

But the following expressions are fine

i = (i, ++i, 1) + 1; //well defined (AFAIK)
i = (++i,i++,i) // well defined 
int j = i;
j = (++i, i++, j*i); // well defined


As no one whinged about that example I accepted it...

So is it actually wrong?

Or it a C++11 versus C++98/C++03 change?


Andy

operator= was not a sequence point...

Any good reason why assignment operator isn't a sequence point?
http://stackoverflow.com/questions/4362501/any-good-reason-why-assignment-operator-isnt-a-sequence-point

But C++11 uses Sequenced Before and Sequenced After relations rather than Sequence Points...

In C++11, how to determine what is 'sequenced before' others?
http://stackoverflow.com/questions/9562562/in-c11-how-to-determine-what-is-sequenced-before-others
Last edited on Jun 22, 2015 at 3:44pm
Jun 22, 2015 at 3:53pm
2011 Standard wrote:
5.17/1 [expr.ass]
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.

It is indeed is an undefined behavior in previous standard versions but C++11 changed it, as i is computed once in operand evaluation, then sequence point happens, then side effect happens.
Topic archived. No new replies allowed.