Sign in to follow this  
Followers 0
Richard Robertson

i = i++;

17 posts in this topic

If I had the C++ code

int i = 0;
i = i++;
std::cout << i;

What do you expect to be written?

Share this post


Link to post
Share on other sites



I... don't understand? Is this supposed to be a trick question? If so, what's the trick supposed to be? The answer should be obvious.

Share this post


Link to post
Share on other sites

I would have expected 0 to be written!

0 would have been stored to i and then the value of i would have been incremented.

OHH, i does store 0 and then it IS incremented afterwards!

Share this post


Link to post
Share on other sites

In the ideal world you get a compiler message:

ERROR: User stupidity level exceeded.
1 person likes this

Share this post


Link to post
Share on other sites

Yes I realize it's a horrible piece of code, but the fact that C++ executes the increment AFTER the assignment really confused me.

I expect 0, and that's what languages like C# and Java do.

Share this post


Link to post
Share on other sites

By the language specification changing the contents of a variable twice in the same statement is undefined behavior. Whatever happens is compiler and platform dependent.

Share this post


Link to post
Share on other sites

This actually started because I saw someone with that code and they wanted to know why their i variable was never incrementing because in their language, (i++) was evaluated before (i =).

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

By the language specification changing the contents of a variable twice in the same statement is undefined behavior. Whatever happens is compiler and platform dependent.

Source?

In this case the behavior is not undefined:

  • Assign i to the value of i (0).
  • Increment i (1)
That's how the post-increment operator works. If the code had used the pre-increment operator and been presented as i = ++i; then the sequence would become:

  • Increment i (1)
  • Assign i to the value of i (1).
The result would not have changed. Edited by Valik

Share this post


Link to post
Share on other sites

Source?

In this case the behavior is not undefined:

  • Assign i to the value of i (0).
  • Increment i (1)
That's how the post-increment operator works. If the code had used the pre-increment operator and been presented as i = ++i; then the sequence would become:

  • Increment i (1)
  • Assign i to the value of i (1).
The result would not have changed.

C99 Standard, Section 6.5 (Expressions), Paragraph 2:

Between the previous and next sequence point an object shall have its stored value

modified at most once by the evaluation of an expression. Furthermore, the prior value

shall be read only to determine the value to be stored.

Share this post


Link to post
Share on other sites

Source?

In this case the behavior is not undefined:

  • Assign i to the value of i (0).
  • Increment i (1)
That's how the post-increment operator works. If the code had used the pre-increment operator and been presented as i = ++i; then the sequence would become:

  • Increment i (1)
  • Assign i to the value of i (1).
The result would not have changed.

So you say post-increment always occurs as if it were a statement immediately after the current statement?

So what do you expect from this code?

int i;

void f(int)
{
    cout << i;
}

void main()
{
    i = 0;
    f(i++);
}

Share this post


Link to post
Share on other sites

I think, it i will be incremented immediately after the assignment is completed.

An assignment in this case is for me:

1) assign to variable

2) initializing the function parameter.

What output do you expect here?

int i;

void f(int a, int <img src='http://www.autoitscript.com/forum/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
{
    cout << i << " " << a << " " << b;
}

int main()
{
    i = 0;
    f(i++, i++);
}

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

In the code I just posted and in your code, I would expect to see "1" and "1 1 1" respectively.

My problem is that in i = i++; is that the increment happens after the statement rather than where the operator occurs. Especially since both pre- and post-increment operators are higher precedence than =.

Edited by Richard Robertson

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Your code outputs 1, mine outputs 2 1 0.

There is another thing to try:

i = i++ = i or something like that... Well if I rethink this, it won't work.

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

danielkza, I'm not interested in C specifications when we are talking about C++.

This is whole topic is absurd, I can't believe we are having this discussion. We're talking about the post-increment operator here. Let's stop using these stupid "i=i" examples and look at something a little less confusing:

int i = 10, j = 0;

j = i++;
std::cout<<"j: "<<j<<", i: "<<i<<std::endl;
This examples prints "j: 10, i: 11". Why? Because we used the post-increment operator. That operator works by assigning the current value of i before incrementing it. The increment happens post everything else - post-increment.

int i = 10, j = 0;
j = ++i;
std::cout<<"j: "<<j<<", i: "<<i<<std::endl;
This example prints "j: 11, i: 11". Why? Because we used the pre-increment operator. That operator works by incrementing the value of i before assigning it. The increment happens pre everything else - pre-increment.

This is basic C++. There are two separate operators with different behavior. It seems people here think that the post-increment operator behaves like the pre-increment operator when it does not. Once you isolate how the operators work then it's trivial to substitute i back in for j since that part of the expression is entirely irrelevant.

The pre-increment operator should be the default people use when the choice doesn't matter. Back in the day - and it could still be true - compilers optimized code better when they encountered pre-increment rather than post-increment. I imagine modern compilers have no issue with this and generate identical code except in cases where assignment is involved, but still, pre-increment is prefered. There are specific cases where you want to use the post-increment operator, however. AutoIt contains a few places where I've specifically used post-increment.

TL;DR version: Learn C++.

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

@Valik:

As you wish:

Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expres-

sions, and the order in which side effects take place, is unspecified. 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. Furthermore, the prior

value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for

each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined

I understood that the specific case of assigning to and incrementing a variable in the same statement was the topic in discussion. That's what I was talking about. In respect to it, pre or post-increment is irrelevant: in both cases the behavior would be undefined because i would be modified twice before a sequence point. In theory it would be possible to write down some rules that would make sense of the code in the OP, but the spec omits them purposely in favor of freedom of implementation. The compiler is free to delay committing of variables to their storage (usually RAM) until a sequence point occurs, and that's why you can't be sure the increment will actually happen before or after the assignment.

Edited by danielkza
1 person likes this

Share this post


Link to post
Share on other sites

According to Wikipedia (for what that's worth), you are correct - barely. I was under the impression that operators had function semantics even when not overloaded. Functions are sequence points. However, an operator only behaves like a function (and acts a sequence point) if it's overloaded. In this case, since the operators are not overloaded, it is undefined behavior.

1 person likes this

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0