C語(yǔ)言執(zhí)行a=a; 后,a的值應(yīng)該加一還是不變?
【語(yǔ)言表達(dá)的簡(jiǎn)明,a語(yǔ)言】
結(jié)論:不同的編譯器,會(huì)得出不同的結(jié)果 。因?yàn)閍 = a這種表達(dá)式,在C語(yǔ)言規(guī)范中是屬于未定義的行為(Undefined behavior) 。以下面這段代碼為例,在Linux上打印0x1234,在Windows上打印0x1235 。下面分別在Windows和Linux上演示,并從匯編的角度,詳細(xì)講解一下 。
Windows(Visual Studio 2015)在Windows上,用VS2015編譯并運(yùn)行,結(jié)果如下:看一下反匯編:藍(lán)色方框內(nèi)指令 mov dword ptr[a], 1234h 給變量a賦初值,也就是0x1234 。紅色方框內(nèi)兩條指令,看起來(lái)挺有意思:第一條:mov eax, dword ptr[a] 把變量a的值加載到寄存器eax中 。
第二條:mov dword ptr[a], eax 又把寄存器eax的值,存放到變量a中 。這兩條指令時(shí)沒(méi)有任何意義的 。綠色方框內(nèi)的三條指令:第一條:mov ecx, dword ptr[a] 把變量a的值加載到寄存器ecx中,也就是0x1234 。第二條:add ecx, 1 把ecx的值加1,此時(shí)ecx = 0x12341 = 0x1235 。
第三條:mov dword ptr[a], ecx 把寄存器ecx的值存放到變量a中,此時(shí)a的值是0x1235,這也是a最終的值 。不難看出,VS2015上,表達(dá)式 “a = a”被翻譯成下面的偽代碼表示:a = 0x1234;eax = a;a = eax;ecx = a;ecx = ecx1;a = ecx;所以,最終變量a的值是0x1235 。
Linux(GCC 8.3.0)同樣的程序,在Ubuntu上用GCC 8.3.0編譯,并運(yùn)行,結(jié)果為0x1234 。如下圖:把GCC編譯生成的目標(biāo)文件進(jìn)行反匯編,如下圖:圖中,關(guān)鍵指令已經(jīng)標(biāo)記出來(lái)了,應(yīng)該比較容易理解了 。不難看出,表達(dá)式“a = a”被GCC翻譯成如下偽代碼:a = 0x1234;eax = a;edx = eax1;a = edx;a = eax;因此,最終變量a的值是0x1234 。
sequence pointC語(yǔ)言中有個(gè)重要的概念 - “sequence point”,有的翻譯為順序點(diǎn)或序列點(diǎn),還有翻譯為執(zhí)行點(diǎn)的 。C語(yǔ)言規(guī)范要求,編譯器必須保證,在某個(gè)sequence point上,它之前的所有表達(dá)式的計(jì)算都已經(jīng)確定,而它之后的所有表達(dá)式計(jì)算都尚未開(kāi)始 。C語(yǔ)言規(guī)范中,對(duì)各種表達(dá)式定義了一系列的sequence point,感興趣的童鞋可以翻閱C語(yǔ)言規(guī)范 。
對(duì)于“a = a;”這個(gè)表達(dá)式,C語(yǔ)言規(guī)范定義的sequence point是最后的分號(hào)“;” 。但是,這個(gè)表達(dá)式中,可能改變a的值的地方卻有兩個(gè):一個(gè)是對(duì)等號(hào)左邊的a賦值的操作,一個(gè)是等號(hào)右邊的a的自加操作 。這兩個(gè)操作之間,并沒(méi)有明確定義的sequence point 。因此,才導(dǎo)致了不同的編譯器采用不同的計(jì)算順序,得出不同的結(jié)果 。
其實(shí),如果編譯時(shí)開(kāi)啟告警選項(xiàng),編譯時(shí)是會(huì)有告警信息的,比如GCC和Clang:建議C語(yǔ)言規(guī)范中,列舉了很多不確定的行為,主要有:Unspecified behaviorUndefined behaviorImplementation-defined behaviorLocale-specific behavior總之,有很多語(yǔ)法規(guī)則,C語(yǔ)言規(guī)范并沒(méi)有定義一個(gè)確定的輸出結(jié)果,不同的編譯器、版本、運(yùn)行時(shí)環(huán)境、OS等都可能會(huì)產(chǎn)生不同的結(jié)果 。
推薦閱讀
- 鹽對(duì)狗狗的危害真的這么大嗎,賣狗的錢為什么買鹽呢
- 拉布拉多狗是什么品種,您真的了解拉布拉多嗎
- 獨(dú)為什么是犭傍,絲綢之路的歷史地理背景
- 用什么軟件拍貓咪好看,什么樣的貓咪好看
- 狗為什么老愛(ài)在地上,為什么天下的狗狗都愛(ài)刨坑
- 三星pl51,我買了三星的PL51相機(jī) 價(jià)格是1270 是貴了還是便宜?。??
- 泰迪犬一般多少錢一支,受歡迎的泰迪犬
- 高端顯卡筆記本,誰(shuí)給推薦幾款中高端顯卡的筆記本4000左右的
- 升級(jí)后的手機(jī)異象
- 堅(jiān)果手機(jī)系統(tǒng),真是卡頓中的王者,老羅,流暢得不像...
