我搜索了x ++ vs ++ x,我找到了一个很好的答案here,所以我决定看看gcc的汇编输出,看看x ++和++ x是如何实现的:
main(){int s = 0; ++ S;返回0; }
编译示例:
gcc mul.c -masm = intel -o mul.asm
输出 ++ 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]"
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]"
所以,我问的是x ++和++ x是否有不同的含义,为什么GCC为它们输出一些汇编,不应该有不同的输出?
答案 0 :(得分:6)
这是一个写得不好的测试用例的例子。永远不会存储表达式value++
或++value
的实际结果,因此编译器可以处理基本类型的等效项。
请改用此示例:
main() { int s = 0, x; x = ++s; return 0; }
main() { int s = 0, x; x = s++; return 0; }
(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)
(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)
答案 1 :(得分:2)
要查看不同的输出,您需要做的不仅仅是增量。
如果没有使用该值,那么++ s和s ++会做同样的事情。main(){int s = 0; int a = ++ s;返回0; }
答案 2 :(得分:2)
它被称为“优化”。
在您的情况下,如果预增量或后增量(它导致完全相同的逻辑流程)无关紧要,因此汇编输出是相同的。
这是一个反例:
/*
* SAMPLE OUTPUT: i++=1, ++j=3
*/
#include <stdio.h>
int
main (int argc, char *argv[])
{
int i = 1, j= 2;
printf ("i++=%d, ++j=%d\n", i++, ++j);
return 0;
}
这是Visual C ++汇编程序输出。您会注意到此示例会增加*“i”和“j”:
; File tmp.c
; Line 5
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
; Line 6
mov DWORD PTR _i$[ebp], 1
mov DWORD PTR _j$[ebp], 2
; Line 7
mov eax, DWORD PTR _j$[ebp]
add eax, 1
mov DWORD PTR _j$[ebp], eax
mov ecx, DWORD PTR _j$[ebp]
push ecx
mov edx, DWORD PTR _i$[ebp]
mov DWORD PTR -12+[ebp], edx
mov eax, DWORD PTR -12+[ebp]
push eax
push OFFSET FLAT:$SG342
mov ecx, DWORD PTR _i$[ebp]
add ecx, 1
mov DWORD PTR _i$[ebp], ecx
call _printf
add esp, 12 ; 0000000cH
; Line 8
xor eax, eax
; Line 9
mov esp, ebp
pop ebp
ret 0
_main ENDP
这是gcc汇编程序,带-O3。您会注意到它没有任何增量:编译器只存储最终值i = 1和j = 3:
.LC0:
.string "i++=%d, ++j=%d\n"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
movl $3, 8(%esp)
movl $1, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $20, %esp
xorl %eax, %eax
popl %ecx
最后,这是优化的 Visual C ++版本(带“/ Ox”)。你会发现这是这三个例子中最短的一个:
; File tmp.c
; Line 7
push 3
push 1
push OFFSET FLAT:$SG399
call _printf
add esp, 12 ; 0000000cH
; Line 8
xor eax, eax
; Line 9
ret 0
_main ENDP