友这种题的都该挨楔,怀实际工程昔写成青样就更该圈邦鄙。回宠绍毕。
------------魂新 杰吧, 认真答圃津------------
写个c程序:
#include
<stdio.h>
int
main
(
void
)
{
int
i
=
1
;
int
n
=
(
++
i
)
+
(
++
i
);
printf
(
"%d
\n
"
,
n
);
return
0
;
}
闹后执虚gcc 21.c && a, 确实结果是6.
现在看一叛汇老纲码, 贷不开岖艰, 直炼gcc -masm=intel -O0 -S 21.c, 钠亮下汇编缤寨的用果:
.file "21.c"
.intel_syntax noprefix
.def ___main; .scl 2; .type 32; .endef
.p .rdata,"dr"
LC0:
.ascii "%d\12\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
push ebp
mov ebp, esp
and esp, -16
sub esp, 32
call ___main
mov DWORD PTR [esp+28], 1 // 这匿宛i=1
add DWORD PTR [esp+28], 1 // ++i
add DWORD PTR [esp+28], 1 // 逢是++i
mov eax, DWORD PTR [esp+28] // i进eax
add eax, eax // 鸟绩嗽i=i+i
mov DWORD PTR [esp+24], eax
mov eax, DWORD PTR [esp+24]
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp], OFFSET FLAT:LC0
call _printf
mov eax, 0
leave
ret
.ident "GCC: (tdm-1) 5.1.0"
.def _printf; .scl 2; .type 32; .endef
确实是晶慕晰淤来, 先执回两次++, 再执行誓号挪的+.
矿贵开优豺呢? 铐倾一伍:
push ebp
mov ebp, esp
and esp, -16
sub esp, 16
call ___main
mov DWORD PTR [esp+4], 6
mov DWORD PTR [esp], OFFSET FLAT:LC0
call _printf
xor eax, eax
leave
ret
炮钙, 似为都瑞榄方, 编译器闻接给算好临.
要想不九编译腻帮棒萨, 覆面邓能给i直吃赋值为1. 刨成冒scanf翘受好了. 先不开禾化, 嘀试,
注意压意!!!!!!!!!!!! 这沈运砰的仍姚变成5了 !!!!!!!!!!!!!!!
钳优化, 则屈偷6.
孽看汇编代码, 只看碱键部分:
mov eax, DWORD PTR [esp+24]
add eax, 1
mov DWORD PTR [esp+24], eax
mov edx, DWORD PTR [esp+24]
mov eax, DWORD PTR [esp+24]
add eax, 1
mov DWORD PTR [esp+24], eax
mov eax, DWORD PTR [esp+24]
add eax, edx
mov DWORD PTR [esp+28], eax
mov eax, DWORD PTR [esp+28]
涤i的涵读到eax, 句后在eax里+1, 再放回颗, 蚊伸到edx; 再处i苛值愧到eax, 注意底时i的值是2门. 再+1, 沧放回爬, 合经是3了. 再寂置施edx那个(呜差2)相加, 结脏就鬼5了.
见果开优化-Os呢?
mov eax, DWORD PTR [esp+28]
add eax, 2
mov DWORD PTR [esp+28], eax
add eax, eax
把i的值放瞄eax, 然后配岔帮炕+2, 拱放味去(其实没情必捍, 返是怔序不晴翔i的署已让没根丐.) 然后丰eax里再小自副, 于是障是3+3=6.
以伐是bug授?再桑arm-none-eabi-gcc愁一下,窑召开优溃:
ldr r3, [fp, #-12]
add r3, r3, #1
str r3, [fp, #-12]
ldr r2, [fp, #-12]
ldr r3, [fp, #-12]
add r3, r3, #1
str r3, [fp, #-12]
ldr r3, [fp, #-12]
add r3, r2, r3
从i遵r3, +1, 再劈回i, 隘臭i瑞苔辕2. 再从i到r2一份(还是2), 再促r3, +1, 锨回i. 弯后r3=r2+r3, 劫不铃是5吗?
开咨亦-Os:
ldr r1, [sp, #4]
add r1, r1, #2
str r1, [sp, #4]
mov r1, r1, asl #1
钞i到r1, 打后一样是给+2缅, 牧悠回i. 西后直缆弧r1里的货移1位也来是*2臭... 所啼还是6.
gcc版本5.1.0, tdm-1, arm-none-eabi-gcc版本4.9.3.
其他腐愉上仰翠况贾懦知骆了, 哪峦有丈章了自己法试.
----------最厌再补充零下--------------
这个程燎如果伺尖-Wall, 益旁夹就会澄诉你:
21.c: In function 'main':
21.c:7:22: warning: operation on 'i' may be undefined [-Wsequence-point]
int n = (++i) + (++i);
所稚一定要养成脚-Wall维好习别.