9

Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)

My code is as follows:

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

Given the nature of post-increment, I would expect the following output:

x: 10
y: 10

My reasoning is that in line 5, x should be assigned to its initial value after the increment takes place.

Instead, however, I get this:

x: 11
y: 11

Digging into the assembly, this looks like a deliberate choice to me:

LCFI2:
        movl    $10, -4(%rbp)   // this is x
        movl    $0, -8(%rbp)    // this is y
        incl    -4(%rbp)        // x is simply incremented
        movl    -4(%rbp), %esi
        leaq    LC0(%rip), %rdi
        movl    $0, %eax
        call    _printf
        movl    -4(%rbp), %eax  // now x is saved in a register,
        movl    %eax, -8(%rbp)  // copied to y,
        incl    -4(%rbp)        // and finally incremented
        movl    -8(%rbp), %esi
        leaq    LC1(%rip), %rdi
        movl    $0, %eax
        call    _printf

What's going on here? Is GCC trying to save me from myself? I don't have a language reference handy but I would have thought that this breaks the intended semantics.

Community
  • 1
  • 1
danben
  • 80,905
  • 18
  • 123
  • 145
  • http://en.wikipedia.org/wiki/Sequence_point – Ken Jul 19 '10 at 02:59
  • In the bad old days, `a = 1 + a` in certain languages was a mine that all the new bugs would tread on. – Brian Hooper Jul 19 '10 at 09:58
  • @caf - you are right, this is a duplicate (although that question unfortunately provides no helpful way to search for it). – danben Jul 19 '10 at 11:57
  • When you say "Instead, however, I get this: x = 11, y =11" , what compiler are you using. I checked on codeblocks and onlinegdb, they both gave me x=10 , y = 10 as expected. – john Dec 23 '19 at 18:08

4 Answers4

13

The behaviour is undefined as there is no intervening sequence point in x = x++, see e.g. the C FAQ.

Georg Fritzsche
  • 97,545
  • 26
  • 194
  • 236
4

It is left undefined by the C language as to when exactly a post/pre-in/decrement occurs. Thus, statements such as x = x++ are not well formed - avoid them.

Thanatos
  • 42,585
  • 14
  • 91
  • 146
  • 1
    More precisely you aren't allowed to modify a variable more than once in an expression. 6.5/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."* – sth Jul 19 '10 at 02:37
  • 2
    @sth: More precisely, "more than one between sequence points". It's possible for an expression to contain a sequence point, in which case modifying a variable more than once is fine. For example, `&&`, `||` and the comma operator can all form sequence points within a single expression. – Jerry Coffin Jul 19 '10 at 02:41
  • @sth: Even _more precisely_, that's not a limitation on the coder, it's a limitation on the variable itself. Your statement that you "aren't allowed to ..." is not quite correct. You _are_ allowed to, it's just a very silly thing to do :-) – paxdiablo Jul 19 '10 at 02:44
  • Yeah, I was aware that the use of the word "precisely" there would cause some follow-up comments. But it was late at night and I was too lazy to explain what a sequence point is... :) – sth Jul 19 '10 at 14:31
2

Standards aside (since this is undefined with respect to the standard), the way it ran is the way I would have expected it.

My rule of thumb is that for a line with x++, you substitute x++ with x and put x += 1 on the following line (or preceding line for pre-increment).

Following that rule of thumb, your code would be written as

#include <stdio.h>
int main()
{
  int x = 10, y = 0;
  x = x; // x: 10
  x += 1; // x: 11
  printf("x: %d\n", x);
  y = x; // y: 11
  x += 1; // x: 12
  printf("y: %d\n", y);
}
Mark Rushakoff
  • 249,864
  • 45
  • 407
  • 398
1

When you have:

a = b++;

what is happening is that b is saved to a and after the assigment is done b is incremented by one. So if you do:

x = x ++;

and previously x was 10 what will happen is 10 will be saved to x and after(before your printf is done) x is incremented by one to 11. That's why 11 is printed.