Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Help with post-increment and sequence points

Reply
Thread Tools

Help with post-increment and sequence points

 
 
laird@lbreyer.com
Guest
Posts: n/a
 
      10-20-2011
#include <iostream>
int main() {
int i = 1;
std::cout << i << i++ << i << "\n";
}

Compiling this code in g++ prints out 212 . Is this correct? If so, I don'tunderstand why.

Shouldn't this actually be equivalent to f(f(f(f(std::cout,i),i++),i),"\n")where f is operator<< ? In that case, each time a function is entered, there should be a sequence point which makes the side effects happen. So I'd expect the output to be 112 instead.

% g++ --version
g++ (Debian 4.6.1-4) 4.6.1

Best regards,
Laird Breyer
 
Reply With Quote
 
 
 
 
softwareEngineer
Guest
Posts: n/a
 
      10-20-2011

Don't do that ....

http://www2.research.att.com/~bs/bs_...aluation-order
<http://www2.research.att.com/%7Ebs/bs_faq2.html#evaluation-order>

bye.


Il 20/10/2011 09:23, ha scritto:
> #include<iostream>
> int main() {
> int i = 1;
> std::cout<< i<< i++<< i<< "\n";
> }
>
> Compiling this code in g++ prints out 212 . Is this correct? If so, I don't understand why.
>
> Shouldn't this actually be equivalent to f(f(f(f(std::cout,i),i++),i),"\n") where f is operator<< ? In that case, each time a function is entered, there should be a sequence point which makes the side effects happen. So I'd expect the output to be 112 instead.
>
> % g++ --version
> g++ (Debian 4.6.1-4) 4.6.1
>
> Best regards,
> Laird Breyer


 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      10-20-2011
On 10/20/2011 3:23 AM, wrote:
> #include<iostream>
> int main() {
> int i = 1;
> std::cout<< i<< i++<< i<< "\n";


This expression actually means
std::cout.
operator<<(i). // #1
operator<<(i++). // #2
operator<<(i). // #3
operator<<("\n"); // #4

Which, in reality means

mem_op<<( // #4
mem_op<<( // #3
mem_op<<( // #2
mem_op<< ( std::cout, i), // #1
i++ ), i ), "\n");

which, according to the Standard can have any order of evaluation of its
operands, except that there is a sequence point before a call to a
function. So, before calling #4, it has to evaluate #3, which means it
will call the function, and in order to do that it has to call #2, and
in order to do that it has to call #1. BUT... The second operands in
all those calls can be evaluated an *any* time after the expression
starts evaluating just before the function call that needs it. IOW, the
*second* arguments could be evaluated as i,"\n",i,i++, and you would see
111, which should still be "correct". Or the order could be
"\n",i++,i,i, which *could* give 211, or 222, depending on when the
effects of ++ take place (they are supposed to take place before the
next "intervening" sequence point).

> }
>
> Compiling this code in g++ prints out 212 . Is this correct? If so, I don't understand why.


It is just as correct as any other combination of 1s and 2s.

>
> Shouldn't this actually be equivalent to

f(f(f(f(std::cout,i),i++),i),"\n") where f is operator<< ? In that case,
each time a function is entered, there should be a sequence point which
makes the side effects happen. So I'd expect the output to be 112 instead.

Yes, but the sequence point has no effect on when the *second* argument
for every call is evaluated. You seem to forget that.

>
> % g++ --version
> g++ (Debian 4.6.1-4) 4.6.1
>
> Best regards,
> Laird Breyer


V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
Nick Keighley
Guest
Posts: n/a
 
      10-20-2011
On Oct 20, 1:26*pm, Victor Bazarov <v.baza...@comcast.invalid> wrote:
> On 10/20/2011 3:23 AM, la...@lbreyer.com wrote:
>
> > #include<iostream>
> > int main() {
> > * *int i = 1;
> > * *std::cout<< *i<< *i++<< *i<< *"\n";

>
> This expression actually means
> * * *std::cout.
> * * * *operator<<(i). * * * * *// #1
> * * * * *operator<<(i++). * * *// #2
> * * * * * *operator<<(i). * * *// #3
> * * * * * * *operator<<("\n"); // #4
>
> Which, in reality means
>
> * * *mem_op<<( * * * *// #4
> * * * *mem_op<<( * * *// #3
> * * * * *mem_op<<( * *// #2
> * * * * * *mem_op<< ( std::cout, i), *// #1
> * * * * * *i++ ), i ), "\n");
>
> which, according to the Standard can have any order of evaluation of its
> operands, except that there is a sequence point before a call to a
> function. *So, before calling #4, it has to evaluate #3, which means it
> will call the function, and in order to do that it has to call #2, and
> in order to do that it has to call #1. *BUT... *The second operands in
> all those calls can be evaluated an *any* time after the expression
> starts evaluating just before the function call that needs it. *IOW, the
> *second* arguments could be evaluated as i,"\n",i,i++, and you would see
> 111, which should still be "correct". *Or the order could be
> "\n",i++,i,i, which *could* give 211, or 222, depending on when the
> effects of ++ take place (they are supposed to take place before the
> next "intervening" sequence point).
>
> > }

>
> > Compiling this code in g++ prints out 212 . Is this correct? If so, I don't understand why.

>
> It is just as correct as any other combination of 1s and 2s.
>
>
>
> > Shouldn't this actually be equivalent to

>
> f(f(f(f(std::cout,i),i++),i),"\n") where f is operator<< ? In that case,
> each time a function is entered, there should be a sequence point which
> makes the side effects happen. So I'd expect the output to be 112 instead..
>
> Yes, but the sequence point has no effect on when the *second* argument
> for every call is evaluated. *You seem to forget that.


with both i and i++ in there is taht undefined behaviour- or merely
implementaion defined behaviour?

 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      10-20-2011
On 10/20/2011 9:06 AM, Nick Keighley wrote:
> On Oct 20, 1:26 pm, Victor Bazarov<v.baza...@comcast.invalid> wrote:
>> On 10/20/2011 3:23 AM, la...@lbreyer.com wrote:
>>
>>> #include<iostream>
>>> int main() {
>>> int i = 1;
>>> std::cout<< i<< i++<< i<< "\n";

>>
>> This expression actually means
>> std::cout.
>> operator<<(i). // #1
>> operator<<(i++). // #2
>> operator<<(i). // #3
>> operator<<("\n"); // #4
>>
>> Which, in reality means
>>
>> mem_op<<( // #4
>> mem_op<<( // #3
>> mem_op<<( // #2
>> mem_op<< ( std::cout, i), // #1
>> i++ ), i ), "\n");
>>
>> which, according to the Standard can have any order of evaluation of its
>> operands, except that there is a sequence point before a call to a
>> function. So, before calling #4, it has to evaluate #3, which means it
>> will call the function, and in order to do that it has to call #2, and
>> in order to do that it has to call #1. BUT... The second operands in
>> all those calls can be evaluated an *any* time after the expression
>> starts evaluating just before the function call that needs it. IOW, the
>> *second* arguments could be evaluated as i,"\n",i,i++, and you would see
>> 111, which should still be "correct". Or the order could be
>> "\n",i++,i,i, which *could* give 211, or 222, depending on when the
>> effects of ++ take place (they are supposed to take place before the
>> next "intervening" sequence point).
>>
>>> }

>>
>>> Compiling this code in g++ prints out 212 . Is this correct? If so, I don't understand why.

>>
>> It is just as correct as any other combination of 1s and 2s.
>>
>>
>>
>>> Shouldn't this actually be equivalent to

>>
>> f(f(f(f(std::cout,i),i++),i),"\n") where f is operator<< ? In that case,
>> each time a function is entered, there should be a sequence point which
>> makes the side effects happen. So I'd expect the output to be 112 instead.
>>
>> Yes, but the sequence point has no effect on when the *second* argument
>> for every call is evaluated. You seem to forget that.

>
> with both i and i++ in there is taht undefined behaviour- or merely
> implementaion defined behaviour?


Well, since no requirement is set on the order in which the calls and
the evaluation of the "second arguments" is going to happen, it is
probably undefined. The "implementation-defined" carries the
requirement to be documented ([defns.impl.defined]), and the order of
evaluating of the arguments does not have to be documented.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
Markus Wichmann
Guest
Posts: n/a
 
      10-20-2011
On 20.10.2011 09:23, wrote:
> #include <iostream>
> int main() {
> int i = 1;
> std::cout << i << i++ << i << "\n";
> }
>
> Compiling this code in g++ prints out 212 . Is this correct? If so, I don't understand why.
>
> Shouldn't this actually be equivalent to
> f(f(f(f(std::cout,i),i++),i),"\n") where f is operator<< ?
> In that case, each time a function is entered, there should
> be a sequence point which makes the side effects happen. So
> I'd expect the output to be 112 instead.


This logic does not hold. You do call

f(f(std::cout, i), i++)

among other functions. However, the order in which the arguments to the
outer function are evaluated is unspecified. Thus you invoke undefined
behaviour. Which means the output could have been "undefined behaviour
detected!" or, indeed, anything.

> % g++ --version
> g++ (Debian 4.6.1-4) 4.6.1
>
> Best regards,
> Laird Breyer


HTH,
Markus
 
Reply With Quote
 
laird@lbreyer.com
Guest
Posts: n/a
 
      10-20-2011
On Thursday, 20 October 2011 23:26:33 UTC+11, Victor Bazarov wrote:
> >
> > Shouldn't this actually be equivalent to

> f(f(f(f(std::cout,i),i++),i),"\n") where f is operator<< ? In that case,
> each time a function is entered, there should be a sequence point which
> makes the side effects happen. So I'd expect the output to be 112 instead.
>
> Yes, but the sequence point has no effect on when the *second* argument
> for every call is evaluated. You seem to forget that.


Victor, this explains why I was confused. I was secretly thinking of the other case

cout << "good " << "news " << "everybody\n";

where the compiler can also evaluate the strings in any order, but this works in that case because they are all constant, so every possible ordering gives the same return value.

Thanks to everybody who responded.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
sequence points and the execution model George C Programming 7 01-20-2009 12:28 AM
The comma operator, and assigning twice between sequence points ais523 C Programming 9 02-09-2008 07:18 PM
volatile and sequence points in (GASP) multithreaded programs Dave Rahardja C++ 8 07-05-2007 05:18 AM
sequence points and evaluation order John Smith C Programming 9 09-06-2006 09:14 PM
bit operations and sequence points Divick C++ 2 09-05-2006 02:15 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57