Unpredictable result of Increment operation

B

bintom

Is there any reason why the following C++ code behaves as it does ?



int i;

i=1; cout << (++i)++; Output: 2

i=1; cout << ++(++i); Output: 3

i=1; cout << (i++)++; Output: Error. LValue required

i=1; cout << ++(i++); Output: Error. LValue required
 
I

Ian Collins

bintom said:
Is there any reason why the following C++ code behaves as it does ?



int i;

i=1; cout << (++i)++; Output: 2
Because it's nonsensical undefined behaviour.
 
B

bintom

Hi Jack,

Thank for your inputs on undefined/invalid uses (rather than
unpredictable results) of ++ operator. It was a great help.

bintom
 
J

James Kanze

Why is it non-sensical? Why is it undefined?

Because the standard says so. You're modifying the same object
twice without an intervening sequence point.
 
B

brno

James Kanze dixit:
Because the standard says so. You're modifying the same object
twice without an intervening sequence point.

Can you tell what is an intervening sequence point ?

Thanks
 
I

Ian Collins

Ian said:
You are right, it is neither. Sorry, I've seen way too many posts that
are and do...
Um, undefined behaviour overload. I was right the first time...
 
I

Ian Collins

brno said:
James Kanze dixit:

Can you tell what is an intervening sequence point ?
A sequence point occurs after the evaluation of a full expression.
"(++i)++;" is an expression with two modifications of i.
 
J

James Kanze

James Kanze dixit:
Can you tell what is an intervening sequence point ?

A sequence point that is guaranteed to occur between the two
operations.

In your example, the only sequence points are the ends of each
full expression, and the call and return from the
ostream::eek:perator<<( int ) function. There's nothing between
the ++i (which modifies i), and the (x)++ (where 'x' is the
result of ++i, i.e. i), which also modifies i.

Note that if i was a type with a user defined operator++, the
code would be well defined, since the user defined operator++ is
a function, and both the function call and the return are
sequence points. Note too, however, that sequence points do not
always create a complete ordering: in something like 'f(++i) +
g(++i)', there are still no sequence points between the two
incrementations, so the code has undefined behavior.
 
J

James Kanze

A sequence point is a definite *moment* in the execution of the
program, at which all the side effects of the previous calculations
have taken place. There are several situations in which a sequence
point (SP) is known to exist. First, there is a SP at a semicolon.
There is a SP after evaluation of all arguments of a function and
just before the call to that function. There is another SP right
after the function returns. There is another SP after each object
is initialised in a definition statement. A comma operator also
introduces a SP, and so does every logical OR and logical AND
operator. I think that's about it. I don't think there are other
sequence points defined.

In 'a ? b : c', between the evaluation of a and either b or c.
The concept of a sequence point is important for allowing the C++
compiler to create certain optimizations when it generates code
from a C++ program. Sequence points are a limitation on the
execution of the program, so too many of those would mean the
code cannot be optimized. Too few of them might mean the code
won't behave predictably.

It's also important to realize that the compiler can reorder
code in an expression significantly, and if any of the legal
reorderings violate the rules, you have undefined behavior. The
classical example is something like:
f( ++ i ) + g( ++ i ) ;
Undefined behavior, since the compiler can legally reorder this
to be as:
tmp1 = ++ i
tmp2 = ++ i
f( tmp1 )
g( tmp2 )
(without any sequence points other than the function calls).

In practice, I (and I suspect that I'm not alone) find it almost
impossible to be 100% sure whether there is a sequence point or
not in some of the more subtle cases. So the general rule is to
just avoid modifying the same variable more than once in an
expression, or modifying it and using it elsewhere in the
expression. About the only exceptions I'll allow are for top
level (not in any parentheses) &&, || and ?:.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top