cgcc

Difference between x++ and ++x in compiler implementation


I searched for x++ vs ++x and I found a great answer here, So I decide to see the assembly output of gcc to see how x++ and ++x implemented:

main() { int s = 0; ++s; return 0; }

Compiling the example:

gcc mul.c -masm=intel -o mul.asm

Output of ++s:

    .file   "mul.c"
    .intel_syntax
    .text
    .p2align 4,,15
.globl main
    .type   main, @function
main:
    lea %ecx, [%esp+4]
    and %esp, -16
    push    DWORD PTR [%ecx-4]
    push    %ebp
    mov %ebp, %esp
    push    %ecx
    sub %esp, 16
    mov DWORD PTR [%ebp-8], 0
    add DWORD PTR [%ebp-8], 1
    mov %eax, 0
    add %esp, 16
    pop %ecx
    pop %ebp
    lea %esp, [%ecx-4]
    ret
    .size   main, .-main
    .ident  "GCC: (GNU) 4.2.1 20070719  [FreeBSD]"      

Output for x++:

    .file   "mul.c"
    .intel_syntax
    .text
    .p2align 4,,15
.globl main
    .type   main, @function
main:
    lea %ecx, [%esp+4]
    and %esp, -16
    push    DWORD PTR [%ecx-4]
    push    %ebp
    mov %ebp, %esp
    push    %ecx
    sub %esp, 16
    mov DWORD PTR [%ebp-8], 0
    add DWORD PTR [%ebp-8], 1
    mov %eax, 0
    add %esp, 16
    pop %ecx
    pop %ebp
    lea %esp, [%ecx-4]
    ret
    .size   main, .-main
    .ident  "GCC: (GNU) 4.2.1 20070719  [FreeBSD]"

So, I am asking if x++ and ++x have different meaning, why GCC outputs the some assembly for them, shouldn't have different output?


Solution

  • This is an example of a not-well written test case. The actual result of the expression value++ or ++value is never stored, as such the compiler can handle both equivalent for basic types.

    Use this examples instead:

    main() { int s = 0, x; x = ++s; return 0; }
    
    main() { int s = 0, x; x = s++; return 0; }
    

    Post-increment:

    (gdb) disas /m main
    Dump of assembler code for function main():
    1       int main(){
       0x0040138c :     push   %ebp
       0x0040138d :     mov    %esp,%ebp
       0x0040138f :     and    $0xfffffff0,%esp
       0x00401392 :     sub    $0x10,%esp
       0x00401395 :     call   0x4018d4 
    
    2               int s = 0;
       0x0040139a :    movl   $0x0,0xc(%esp)
    
    3               int x;
    4               x = s++;
       0x004013a2 :    mov    0xc(%esp),%eax
       0x004013a6 :    mov    %eax,0x8(%esp)
       0x004013aa :    incl   0xc(%esp)
    
    5               return 0;
       0x004013ae :    mov    $0x0,%eax
    
    6       }   0x004013b3 :   leave
       0x004013b4 :    ret
    
    End of assembler dump.
    (gdb)

    Pre-increment:

    (gdb) disas /m main
    Dump of assembler code for function main():
    1       int main(){
       0x0040138c :     push   %ebp
       0x0040138d :     mov    %esp,%ebp
       0x0040138f :     and    $0xfffffff0,%esp
       0x00401392 :     sub    $0x10,%esp
       0x00401395 :     call   0x4018d4 
    
    2               int s = 0;
       0x0040139a :    movl   $0x0,0xc(%esp)
    
    3               int x;
    4               x = ++s;
       0x004013a2 :    incl   0xc(%esp)
       0x004013a6 :    mov    0xc(%esp),%eax
       0x004013aa :    mov    %eax,0x8(%esp)
    
    5               return 0;
       0x004013ae :    mov    $0x0,%eax
    
    6       }   0x004013b3 :   leave
       0x004013b4 :    ret
    
    End of assembler dump.
    (gdb)