tags:

views:

476

answers:

12

Possible Duplicates:
What is more efficient i++ or ++i?
How do we explain the result of the expression (++x)+(++x)+(++x)?
Difference between i++ and ++i in a loop?

Hi I am trying these two programs

void fun(){
     int k=0;
     int i=10;
     k = (i++)+(++i);
     cout<<k<<endl;

}
Output = 22 as i++ will give 10 and ++i will evaluate into 12

but

void fun(){
     int k=0;
     int i=10;
     k = (++i)+(++i);
     cout<<k<<endl;

}
Output = 24

It should be 23 I guess or there is sth that I am not able to see

Thanks in advance

+18  A: 

Note: you are invoking undefined behavior (modifying a variable twice between sequence points)

Brian
Brian's is the correct answer. This is paragraph 2 of ANSI C standard section 6.3 "Expressions" -- "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 accessed only to determine the value to be stored."
Heath Hunnicutt
It's a bit scary to see how many people answered the question *without* catching the undefined part. Sadly enough, still most people consider whatever works with their compiler and test cases to be "valid"...
DevSolar
I think the reason why people answered (including me) is that the question is "What is going on?". I think many people just try to explain why based on the behaviors that is visible. I personally never use '++' operator except in for loop.
NawaMan
But the point is, if behaviour is *undefined* as by spec, any explanation of "what is going on" is uncertain at best, and keeps the OP unaware of the potentially fatal programming flaw at worst.
DevSolar
A: 

I'm guessing that both pre-increment operators are running before the addition statement gets calculated. hence 24.

All depends on how the compiler sees what you're doing, but I'm guessing that's what you're seeing.

Deeksy
It all depends on how the compiler orders sub expressions.
Martin York
A: 

++i happens before calculating the whole expression and i++ happens after. In the first example one of increments happen before calculating the value, so "i" becomes 21 and you get 21 + 21. In the last example both happen before, so "i" becomes 22 and you get 22 + 22.

ratatosk
A: 

i++ is post-increment, ++i is pre-increment. i++ will increment i after the statement is completed.

To illustrate in your examples:

Example 1:

k = 0
i = 10

i += 1
k = i + i  // 11 + 11
i += 1

Example 2:

k = 0
i = 10

i += 1
i += 1
k = i + i  // 12 + 12
Josh
Man! Your explanation is much more concise. :-D
NawaMan
It's also equally incorrect. The OP's code invokes undefined behavior, which this code does not do because `i` is never assigned to more than once in any statement. Therefore, the OP's code can do anything the compiler writers want it to, but this code will be well-defined for all compilers. It's useless to try to explain undefined behavior, and much better to rewrite it to be defined behavior.
Chris Lutz
This doesn't really answer the question of why the compiler sees it this way rather than assigning the result to two temporaries and then adding both of those.
Ken Bloom
A: 

++i will give result i=i+1. If i=10 then in k = (++i)+(++i); expression (++i) will give incremented value that means first increment will happen but in case of i++ the increment will be affected on i after the expression.

So i=10

k = (i++) + (++i);

 10    11   12

 10    +  12=22

k = (++i) + (++i);

 11   11  12

  11   +  12=23
Himadri
But he wants to know why he gets 24 where you just got 23 doing it by hand.
Ken Bloom
The results are dependent on how the compiler re-orders sub-expressions within the output code. So there are actually multiple different valid solutions (valid for a compiler engineer standpoint not from a language stand point).
Martin York
A: 

++i usually returns a reference to the variable itself so the second modification also affects the memory that holds the result from the first modification. (Post-increment i++, on the other hand, has to return a copy of the value in order to work properly.)

A typical definition of ++i in C++ (using operator overloading) would be

struct Foo{
  //...
  Foo const & operator++(){ //this implements ++i
    //do something to increment
    return *this;
  }
  Foo operator++(int){ //this implements i++
    Foo old(*this);
    //do something to increment
    return old;
  }
};
Ken Bloom
@kbloom, you'd normally implement the post-increment operator in terms of the pre-increment operator. So your comment "//do something to increment" in your post-increment operator would simply invoke the pre-increment operator. See Herb Sutter's Guru of the Week article for details: http://www.gotw.ca/gotw/004.htm
Void
That's certainly true. My point, however, was to explain why both pre-increment operators seem to return even numbers (or why both seem to return odd numbers) when it would seem that one should return an even number and one should return an odd number. The answer to that is that preincrement returns the actual memory location of the value that was incremented -- not a copy.
Ken Bloom
+3  A: 

This seemed really interesting, so I took a peek at the disassembly (MSVC++2008)

     k = (++i)+(++i);
0122413C  mov         eax,dword ptr [i] 
0122413F  add         eax,1 
01224142  mov         dword ptr [i],eax 
01224145  mov         ecx,dword ptr [i] 
01224148  add         ecx,1 
0122414B  mov         dword ptr [i],ecx 
0122414E  mov         edx,dword ptr [i] 
01224151  add         edx,dword ptr [i] 
01224154  mov         dword ptr [k],edx

As you can see, it increments i twice and then adds i to itself. The same thing happens if there are multiple instances of (++i).

Anyway, since the Standard doesn't guarantee anything, modifying i more than once will lead to undefined behaviour.

Jacob
A: 

To determine this the following step is taking.

1). All of ++i is determined.

2). The value of i is then used to each term that is ++i and i++.

3). All of i++ is determined.

First case:

     int k=0;
     int i=10;
     k = (i++)+(++i);

1) There is one of ++i so at then end of this step i = 11 (once).

2) Now it become k = (11)+(11);

3) There is one of i++ so at then end of this step i = 12 (once).

Second case:

     int k=0;
     int i=10;
     k = (++i)+(++i);

1) There is one of ++i so at then end of this step i = 12 (twice).

2) Now it become k = (12)+(12);

3) There is one of i++ so at then end of this step i = 12 (zero time).

I create a test code:

#include <stdio.h>
int main(void) {
    int K=0;
    int I=10;
    K = (I++)+(++I);
    printf("I: %d; K: %d\n", I, K);

    K=0;
    I=10;
    K = (++I)+(++I);
    printf("I: %d; K: %d\n", I, K);
}

When executed, the result is:

I: 12; K: 22
I: 12; K: 24

Hope this helps.

NawaMan
So, in your example, the FIRST case should print an odd number (that's what you got when you did it by hand), but it printed an even number when you ran it. He wants to know what's up with that.
Ken Bloom
How can it be an odd number, (11)+(11) is 22 not an odd number. Please read number 2) carefully, the value of `++i` is used for both `++i` and `i++` because i of `i++` will be increased later (so before it is increased, it is 11 as it was increased by `++i`). That is why, K is (11)+(11).
NawaMan
There's no determenistic explanation for the program's behavior because the behavior is undefined. In practice, the result will differ from one compiler to another, for different translation settings in the same compiler, and even for differetn contexts in the same program. The "explanation" that you provided is completely useless, since the actual behavior is essentially random.
AndreyT
Ken Bloom
+6  A: 

According to C++03 Standard 5/4 the behavior of the programs in question is undefined:

Except where noted, the order of evaluation of operands of individual operators and subexpressions of indi- vidual expressions, and the order in which side effects take place, is unspecified. 53) 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.

Kirill V. Lyadvinsky
A: 

Hi

I don't know whether you understand pre and post increment properly. But visualize it this way

pre increment

k=0;
i=10;
k = (++i)+(++i);

first ++i increments value of i to 11.

second ++i increments it to 12.

than those values are added.

i.e.

i = i + 1;
i = i + 1;
k = i + i;(at this state value of i is equal to 12 therefore you get k = 24)


post increment

 int k=0;
 int i=10;
 k = (i++)+(++i);

think of i++ will increment value of i after current statement.

i.e. we have one pre increment and one post increment in this example.

so, it will execute in sequence like this

i = i + 1; ( one pre increment statement)
k = i + 1; ( Current statement . At this stage value of i is 11. Therefore you get k=22)
i = i + 1; ( Post increment statement)

In short value of variable is incremented before or after the execution of statement in which they are used in manner ++i or i++ respectively.

changed
This is wrong. The order in which things are done (aka precedence rules) when `++i` or `i++` are used more than once in one statement, is undefined. It may change from compiler to compiler or system to systme.
Nathan Fellman
+2  A: 

A variable never should be increased more than one time within one statement, because the behaviour of the compiler isn't defined.

To avoid side effects, make two statements for your examples.

Example 1: k = i++; k += ++i;

Example 2: k = ++i; k += ++i;

If you do so, your code will work correctly.

Alfons Mittelmeyer
A: 

Thanks Guy's I understand a lot from this example.

aR