Tricky increment example

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?
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.
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)
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
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)
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
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.