999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

不同編譯器下自增自減表達(dá)式輸出不同值的研究

2023-12-25 03:25:04陳賢敏湯海晨陳治帆
電腦知識與技術(shù) 2023年31期

陳賢敏 湯海晨 陳治帆

摘要:同一個(gè)C語言的自增、自減表達(dá)式為什么在不同集成系統(tǒng)開發(fā)環(huán)境中產(chǎn)生不一樣的結(jié)果。使用GCC和Clang兩種不同的編譯器來驗(yàn)證此實(shí)例表達(dá)式的值,并把兩種編譯好的C語言程序反編譯成匯編語言,再來分析代碼,目的是讓大家真正從底層了解為什么相同的表達(dá)式值會產(chǎn)生不同的結(jié)果。

關(guān)鍵詞:自增自減;GCC;Clang

中圖分類號:TP311? ? ? 文獻(xiàn)標(biāo)識碼:A

文章編號:1009-3044(2023)31-0059-02

開放科學(xué)(資源服務(wù))標(biāo)識碼(OSID)

0 引言

C語言中的自增自減運(yùn)算符(++和--)簡潔、緊湊、靈活。學(xué)生在做練習(xí)中遇到由自增自減運(yùn)算符組成的復(fù)雜算術(shù)表達(dá)式,如p=(i++) +(i++) +(i++) 時(shí),在不同的編譯器中可能會得到不同的運(yùn)行結(jié)果[1],會讓用戶產(chǎn)生茫然疑惑。

國內(nèi)對于C語言中的++、--用例有許多針對性的探討和研究,朱恩亮[2]在《Visual C ++與Turbo C處理自增自減運(yùn)算表達(dá)式的區(qū)別》一文中列舉了在Visual C ++、Turbo C編程語言環(huán)境中,通過操作符的連接,可以構(gòu)造出具有不同復(fù)雜程度的表達(dá)式。分析了i=3,表達(dá)式s1=(++y)+(++y)+(++y)值分別是s1=5+5+6=16和s1=6+6+6=18,產(chǎn)生不同結(jié)果是由于在C語言中操作符存在著優(yōu)先級與結(jié)合性,并構(gòu)造表達(dá)式后,不同語言系統(tǒng)的編譯會產(chǎn)生不同的結(jié)果。

夏超群[3]在《淺析C語言自增自減運(yùn)算符的使用》一文,其例2的語中p=(i++) +(i++) (i++) 從理論上分析該語句中表達(dá)式(i++) +(i++) +(i++) 的值應(yīng)為5+6+7,實(shí)際卻是VC++6.0環(huán)境下運(yùn)算結(jié)果都是5+5+5。文中說明后置自增自減運(yùn)算符的“先用后變”的“變”是指在下一條語句執(zhí)行前統(tǒng)一改變,而不是剛用完就變。故該語句等價(jià)于:p=i+i+i;i=i+1;i=i+1;i=i+1。造成這種結(jié)果是因?yàn)楦呒壵Z言的一條語句經(jīng)編譯解釋成若干條機(jī)器指令,這若干條機(jī)器指令的順序最終決定該等價(jià)高級語言語句的執(zhí)行結(jié)果。

為什么編譯系統(tǒng)會產(chǎn)生這兩種結(jié)果,以上作者的文中并未從源頭給出答案。因此本文通過把C程序代碼編譯后轉(zhuǎn)換成匯編語言并分析代碼的執(zhí)行順序,真正從底層了解不同的編譯器為什么會產(chǎn)生不同的結(jié)果。

1 C語言實(shí)例

#include <stdio.h>

int main() {

int accumulate,i=5;

accumulate=(++y)+(++y)+(++y);

printf("accumulate=%d,i=%d",accumulate,y);

return 0;

}

大家看到此實(shí)例中的表達(dá)式accumulate=(++y)+(++y)+(++y),第一反應(yīng)給出的答案為6+7+8,結(jié)果值為21,y的值為8,那是否正確呢?其實(shí)還可以給出第二種答案accumulate的值為22,y的值為8。

此實(shí)例C語言中的表達(dá)式accumulate=(++y)+(++y)+(++y)的背后運(yùn)算到底是怎樣的一個(gè)過程,為什么此實(shí)例程序中的變量y等于5,最終程序運(yùn)行會產(chǎn)生兩種不同的結(jié)果,分別是22和21。下面通過GCC編譯器模式和Clang編譯器模式驗(yàn)證此實(shí)例在不同的編譯器得出的結(jié)果值是不一樣的。

1.1 實(shí)驗(yàn)1

實(shí)驗(yàn)環(huán)境操作系統(tǒng)是CentOS Linux,GCC編譯器模式,值為accumulate=22,y=8。通過GCC反編譯實(shí)例后如圖1,為了便于理解,圖2根據(jù)圖1一一對應(yīng)寫成C語言格式,使讀者更好地理解匯編語句。

可以看出,表達(dá)式accumulate=(++y)+(++y)+(++y),語句(1) 先把[rbp-4]當(dāng)成i變量,理解成把5賦給[rbp-4]變量,add DWORD PTR [rbp-4],1;語句(2) 相當(dāng)于表達(dá)式中的第一項(xiàng)(++y) ,加1執(zhí)行后[rbp-4]變量值6,i變量自然也是6了,執(zhí)行語句(3) 匯編語句,相當(dāng)于表達(dá)式中的第二項(xiàng)(++y) ,在原來[rbp-4]的基礎(chǔ)上又加1,得[rbp-4]值為7,自然i的值為7。語句(4) 簡單點(diǎn)說,就是把7賦給eax。難道繼續(xù)加1是i的值被替換成8嗎?顯然不是,語句(5) lea edx,[rax+rax] ,理解為edx=7+7=14此時(shí)才明白為什么在C語言中前兩項(xiàng) (++y)+(++y)相加,也就是accumulate=7+7+(++y)。到這里讀者有點(diǎn)不理解了,這個(gè)rax為什么等于7。簡單解釋一下,32位和64位寄存器不是分開的寄存器,它們是重疊的:64位的rax,具有eax作為其底部的32位。因此,對32位寄存器的修改會反映在相應(yīng)的64位寄存器中,反之亦然。繼續(xù)看語句(6) 中[rbp-4]是多少呢,它在執(zhí)行語句(3) 后值沒有改變過,依舊是7,因此執(zhí)行(6) add DWORD PTR [rbp-4],1。相當(dāng)于表達(dá)式中的第三項(xiàng)(++y) ,[rbp-4]值為8,語句(7) [rbp-4]賦給了eax,eax值為8。繼續(xù)執(zhí)行語句(8) add eax,edx ,可以把該語句轉(zhuǎn)換成熟悉的語句eax=eax+edx,已知文中語句(5) 已得出edx=14,因此可得出eax=eax+edx=8+14=22,如圖3所示。

1.2 實(shí)驗(yàn)2

分析完了GCC編譯器模式,現(xiàn)以值為accumulate=21,y=8,按照同樣的方式分解一下由Clang編譯器模式編譯的程序,就會發(fā)現(xiàn)情況有所不同。

通過圖4、圖5可以看出,表達(dá)式accumulate=(++y)+(++y)+(++y),先通過語句(1) 、(2) ,把5賦給eax,語句(3) 累加1后把值賦給eax寄存器,eax值為6,相當(dāng)于表達(dá)式第一項(xiàng)(++y)的值,注意先把第一項(xiàng)值6保留在eax寄存器,通過語句(4) 、(5) 把eax值為6賦給ecx,執(zhí)行語句(6) ecx累加1后,值為7,相當(dāng)于表達(dá)式第二項(xiàng)(++y),把第二項(xiàng)值也是獨(dú)立保存在ecx寄存器中。語句(8) eax=eax+ecx,得eax=6+7=13,從語句(9) 、(10) 可得出表達(dá)式第三項(xiàng)(++y)值為ecx=7+1=8,語句(12) 的結(jié)果為eax=eax+ecx=13+8=21,如圖6所示。

2 實(shí)驗(yàn)結(jié)果分析

現(xiàn)在才明白實(shí)驗(yàn)1中編譯器前兩項(xiàng)自增后,GCC編譯是前兩次y,(++y)+(++y)+(++y),原因是首先掃描求解前半部分,即(++y)+(++y)的值,先對y變量進(jìn)行兩次自增運(yùn)算,y的值變?yōu)?,再計(jì)算y+y的值為7+7=14,然后再求解后半部分,即14+(++y)的值,先對變量y自增1次,y的值變?yōu)?,再計(jì)算14+8=22,因此最終accumulate的值為22,y的值為8。

實(shí)驗(yàn)2中,用Clang編譯器,再反編譯為匯編語言。通過匯編語言可以看出,前兩項(xiàng)y的值都分別獨(dú)立賦給不同的寄存器eax和ecx,因此前兩項(xiàng)(++y) 中的y就不會累加后再賦給相同的寄存器。而實(shí)驗(yàn)1中(2) 、(3) 中兩條語句是對y進(jìn)行累加后賦給,由原來的初值5變化7后,再賦給寄存器eax。

文中的實(shí)例accumulate=(++y)+(++y)+(++y)只是來證明這樣的式子在不同的編譯系統(tǒng)中會產(chǎn)生不同的值,因此在實(shí)際的工作生產(chǎn)和教學(xué)中不建議這樣來使用。任何類似(y++)+(y++)、(++j)+(++j)這樣的表達(dá)式,都屬于未定義行為。可以這么說,在C語言標(biāo)準(zhǔn)中沒有規(guī)定這樣的表達(dá)式應(yīng)該如何計(jì)算,完全由編譯器自行決定,說到底編譯器也是由程序員來開發(fā)出來,當(dāng)然不同的人有不同的邏輯理解,這樣也就導(dǎo)致不同的集成開發(fā)環(huán)境編譯器下自增和自減處理邏輯的不同。也進(jìn)一步說明,由于自增自減表達(dá)式結(jié)果的不確定性,也就不具有可移植性,是十分不友好的表達(dá)式。

通過以上實(shí)例驗(yàn)證,相同的表達(dá)式運(yùn)行結(jié)果得出的值不一樣是由不同集成開發(fā)環(huán)境中的不同編譯器編譯造成的。實(shí)驗(yàn)1、實(shí)驗(yàn)2論證了使用GCC、Clang兩種不同的編譯器對同一段C語言源代碼進(jìn)行編譯,得到了不同的值,它們按照各自思路轉(zhuǎn)化為了匯編代碼,通過對匯編語言的分析,最終找到了相同源代碼在不同的集成開發(fā)環(huán)境下結(jié)果是不一致的,這也是寫本篇論文的目的和任務(wù)。也通過上述實(shí)驗(yàn)發(fā)現(xiàn)Clang的編譯器更能符合正常人的思維邏輯,在今后的學(xué)習(xí)工作中更推薦使用Clang編譯器的開發(fā)環(huán)境。

3 結(jié)束語

C語言中自增運(yùn)算符為“++”,其作用是使變量的值增1;自減運(yùn)算符為“--”,其作用是使變量的值減1[4]。當(dāng)初制定這兩個(gè)C語言運(yùn)算符是為了方便程序使用,但在使用y++、--y不恰當(dāng)時(shí)會造成混淆,給剛?cè)腴T學(xué)習(xí)C語言的人員帶來混亂。

當(dāng)然,像文中的實(shí)例代碼移植性差,需要大家盡量避免,分析這樣的運(yùn)算順序也沒有任何意義。建議大家盡量不要去研究這樣的表達(dá)式,也更不要在實(shí)際編程中寫出這樣的表達(dá)式。所以,在編寫程序時(shí),有選擇地小心謹(jǐn)慎使用自增(自減)運(yùn)算符來簡化程序,在一些容易出錯(cuò)的地方可以用其他方法代替,從而保證程序的執(zhí)行萬無一失[5]。當(dāng)然在實(shí)際項(xiàng)目中,考慮到項(xiàng)目遷移等問題,建議不要使用連續(xù)自增、自減進(jìn)行運(yùn)算,這種邏輯問題在項(xiàng)目維護(hù)過程中很難被發(fā)現(xiàn)和維護(hù)。

參考文獻(xiàn):

[1] 袁玲.在DEV C++環(huán)境下C語言自加自減運(yùn)算符使用分析[J].電腦知識與技術(shù),2016,12(27):248-249.

[2] 朱恩亮.Visual C+ +與Turbo C處理自增自減運(yùn)算表達(dá)式的區(qū)別[J].鹽城工學(xué)院學(xué)報(bào)(自然科學(xué)版),2003,16(3):27-28,31.

[3] 夏超群.淺析C語言自增自減運(yùn)算符的使用[J].武漢工程職業(yè)技術(shù)學(xué)院學(xué)報(bào),2010,22(3):47-49.

[4] 周亮.淺談C語言中自增自減運(yùn)算符的應(yīng)用[J].電腦知識與技術(shù),2010,6(17):4714-4715.

[5] 唐婷,呂浩音.C語言自增(自減)運(yùn)算符運(yùn)算規(guī)律的探討[J].隴東學(xué)院學(xué)報(bào),2016,27(5):8-11.

【通聯(lián)編輯:謝媛媛】

主站蜘蛛池模板: 三上悠亚在线精品二区| 91精品视频在线播放| 国产尤物视频网址导航| 夜夜操国产| 日韩午夜福利在线观看| 2021精品国产自在现线看| 亚洲VA中文字幕| 国产成人午夜福利免费无码r| 女人18毛片水真多国产| 免费人成网站在线观看欧美| 波多野结衣一区二区三区四区视频 | 亚洲A∨无码精品午夜在线观看| 91无码视频在线观看| 91欧美亚洲国产五月天| 国产亚洲欧美日韩在线一区二区三区| 91久久青青草原精品国产| 综合五月天网| 欧美激情视频一区| 国产小视频免费| 91久久夜色精品| 日韩不卡高清视频| 亚洲欧美不卡视频| 国产亚洲精品资源在线26u| 99视频在线免费| 99视频有精品视频免费观看| 国产经典在线观看一区| 免费99精品国产自在现线| 精品一区二区三区波多野结衣| 欧美、日韩、国产综合一区| 亚洲国产午夜精华无码福利| 中文精品久久久久国产网址 | 婷婷六月综合网| 国产精品成人不卡在线观看 | 精品一区二区三区无码视频无码| 夜夜操天天摸| 澳门av无码| 蜜桃视频一区| 精品无码人妻一区二区| 免费看a级毛片| 久久99精品久久久大学生| 国产一区免费在线观看| 极品尤物av美乳在线观看| 又爽又大又黄a级毛片在线视频 | 精品无码国产一区二区三区AV| 日韩国产综合精选| 日韩精品一区二区深田咏美| 97国产精品视频自在拍| 自偷自拍三级全三级视频| 亚洲天堂伊人| 国产电话自拍伊人| 999国产精品永久免费视频精品久久| 国产午夜在线观看视频| 国产亚洲日韩av在线| 久久精品aⅴ无码中文字幕| 精品久久久久久成人AV| 无码高清专区| 久久人人妻人人爽人人卡片av| 色老二精品视频在线观看| 啪啪国产视频| 婷婷激情亚洲| 国产午夜不卡| 人妻精品久久久无码区色视| 国产人人干| 曰AV在线无码| 国内精品久久久久鸭| 亚洲综合第一区| 91视频精品| 国产办公室秘书无码精品| 亚洲国产精品日韩专区AV| 亚洲另类色| 一区二区三区精品视频在线观看| 国产微拍精品| 波多野结衣一区二区三区AV| 91精品国产综合久久不国产大片| 亚洲精品国产精品乱码不卞 | 日本日韩欧美| 亚洲无码视频喷水| 99这里只有精品6| 激情五月婷婷综合网| 国产簧片免费在线播放| 中文字幕亚洲精品2页| 国产主播福利在线观看|