int a=3;
cout<<a++<<" "<<++a;

what is the expected output of this problem ? It is undefined behaviour as it is updating value of "a" once more than once in a sequence point ? Correct me if i am wrong at any point. thanks if you can help me.

You start with a = 3. So line 2 will print a which is 3 then a gets incremented to 4. then it prints the space. Then a gets incremented to 5 then a which is 5 gets printed agian.

This has to do with how the post and pre increment operators work. a++ means give me a then add 1 to it. ++a means add 1 to a then give me what a now holds.

but have you read my questions which i have written ? Please clearfiy them that why is it not undefined ? I mean they are incremented between one sequqnce point. is it okay ? If Yes, then Why ? thanks.

Yes, it's undefined behavior. << does not introduce a sequence point, so you are indeed modifying a twice without a sequence point in between.

The point is that you could evaluate the operands in any order. Lets add some parentheses:

( 
  ( 
    ( cout ) 
    << 
    ( a++ ) 
  ) 
  << 
  ( " " ) 
) 
<< 
( ++a );

For any of the << in the above expression, the stuff above it or the stuff below it (i.e., its operands), could be evaluated first, and you cannot know which (i.e., it is "undefined"). It will be whichever the compiler chooses (arbitrarily or not). So, clearly, there is no telling which of the increment operators will be evaluated first. And thus, it is "undefined behavior".

A sequence point is just a point at which you can tell that all the stuff that appears before it has been evaluated (or at least, the code behaves as if it has all been evaluated) and none of the stuff that appears after it has been evaluated (again, this is about observable behavior, of course). Because the order of operand / function-parameter evaluation is undefined, there cannot be such a point in the midst of an expression such as the one in this example. So, for the most part, sequence points coincide with where you'd find semi-colons (;) in the code (with the exception of short-circuit operators like && and ||). Also note that sequence points only refer to observable behavior on a single thread of execution, it does not imply anything about actual underlying operations (instructions), which could shuffled around or optimized away, as long as the single-threaded observable behavior is preserved (you need memory barriers to enforce stricter sequence points).

And yes, NathanOliver was wrong.

Edited 3 Years Ago by mike_2000_17: precision

Enable all warnings and the compiler will point you in the right direction.

#include <iostream>

int main()
{
    int a=3;
    std::cout<< a++ << " " << ++a ; 
    // *** warning: operation on 'a' may be undefined
}

It is undefined behaviour in both C++98 (which has the old sequence point rules) and C++11 (which does not have sequence points, but uses sequenced-before rules instead).
See: http://en.cppreference.com/w/cpp/language/eval_order

Is it me, or doesn't the C++11 version just change the language that expresses the rules (which is definitely clearer)? Except for the addition of rules for the initializer lists, it doesn't seem like there is anything different (which I guess is required for C++98 compatibility). Only the language changed.

It will be whichever the compiler chooses (arbitrarily or not). So, clearly, there is no telling which of the increment operators will be evaluated first. And thus, it is "undefined behavior".

You seem to be implying that the behavior will definitely be that of one of the possible orderings, but that's not the case. It's just not unspecified, which increment happens first - the behavior is completely undefined. As far as the standard is concerned, the code may print "23 42" or even crash.

In fact gcc produces "4 5" as the output, which is neither consistent with a++ being evaluated first (that should produce "3 5"), nor with ++a evaluated first (that should produce "4 4").

So, for the most part, sequence points coincide with where you'd find semi-colons (;) in the code (with the exception of short-circuit operators like && and ||).

The comma operator and the conditional operator introduce sequence points as well. As do function calls (that is there is a sequence point between the evaluation of the arguments and the evaluation of the body - there is no sequence point between the function's arguments).

Speaking of function calls, I need to correct my earlier answer: The fact that the built-in << operator does not introduce a sequence point is irrelevant because here we're using an overloaded << operator and overloaded operators behave like function calls. This doesn't change that the behavior is undefined though since there is no sequence point between arguments to functions and both arguments to the second call to operator<< modify x.

Comments
Yes

You seem to be implying that the behavior will definitely be that of one of the possible orderings, but that's not the case. It's just not unspecified, which increment happens first - the behavior is completely undefined. As far as the standard is concerned, the code may print "23 42" or even crash.
...
Speaking of function calls, I need to correct my earlier answer: The fact that the built-in << operator does not introduce a sequence point is irrelevant because here we're using an overloaded << operator and overloaded operators behave like function calls.

Yes.

Because an int is a scalar.

If a was an object of a user defined type (with increment operators),
std::cout << ++a << ' ' << a++ ; would not result in UB; it is still bad because the evaluations of ++a and a++ would be 'indeterminately sequenced'

...

C++11 version just change the language that expresses the rules (which is definitely clearer)?

C++11 does make the rules clearer. The canonical pedantic (unclear in C++98) example being:
int k = ( f(), g() ) + h() ;

Sequence-point rules had to be discarded and replaced by sequenced-before rules because C++11 is thread and concurrency aware, while C++98 was not. The new rules allow implementations to generate extremely efficient code and at the same time precisely specify the behaviour of the abstract machine.

Edited 3 Years Ago by vijayan121

This article has been dead for over six months. Start a new discussion instead.