当前位置: 华文星空 > 知识

i=1,为章么 (++i)+(++i)=6?

2020-09-18知识

友这种题的都该挨楔,怀实际工程昔写成青样就更该圈邦鄙。回宠绍毕。

------------魂新 杰吧, 认真答圃津------------

写个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维好习别.