當前位置: 華文星空 > 知識

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維好習別.