国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

剖析C語(yǔ)言自增運(yùn)算規(guī)律

2017-11-28 13:07李云超
科技創(chuàng)新導(dǎo)報(bào) 2017年27期
關(guān)鍵詞:C語(yǔ)言

李云超

摘 要:C語(yǔ)言中提供的自增運(yùn)算符能讓程序的書寫更加簡(jiǎn)便和靈活,但如果運(yùn)用不當(dāng)也會(huì)使 程序的運(yùn)行結(jié)果與預(yù)期大相徑庭,再者,現(xiàn)在的教程中并未從不同編譯器的編譯執(zhí)行角度進(jìn)行深入剖析,使得初學(xué)者對(duì)一些語(yǔ)句有諸多困惑。本文通過實(shí)驗(yàn),利用不同的環(huán)境編寫調(diào)試程序,并對(duì)運(yùn)行結(jié)果進(jìn)行反匯編分析,總結(jié)出自增運(yùn)算符在不同編譯環(huán)境中的運(yùn)算規(guī)律以及在教學(xué)過程中的注意事項(xiàng)。

關(guān)鍵詞:C語(yǔ)言 自增 反匯編

中圖分類號(hào):TN925 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1674-098X(2017)09(c)-0143-03

Abstract: The auto-increasing operator in C language can make writing more convenient and flexible, but it can also make the result different with expected if used undeserved, moreover, the tutorials do not analyze deeply in the angle of different compliers comping and executing, and that makes beginners be confused with some codes. This article analyze the result with disassembling in different compliers, then conclude the rules of auto-increasing and notices in the teaching process.

Key Words: C language; Auto-increasing; Disassemble

C語(yǔ)言歷經(jīng)了幾十年,成為經(jīng)典的編程語(yǔ)言,憑借語(yǔ)句的精煉、語(yǔ)法的靈活、對(duì)系統(tǒng)環(huán)境要求低、擁有較高的執(zhí)行效率而風(fēng)靡整個(gè)世界,再經(jīng)過歷代改進(jìn),C語(yǔ)言發(fā)展至今非但未被淘汰,更是廣泛的應(yīng)用于各種生產(chǎn)環(huán)境中,并且早已成為計(jì)算機(jī)專業(yè)學(xué)生的入門語(yǔ)言。

作為語(yǔ)句精煉的語(yǔ)言,比早期的匯編語(yǔ)言簡(jiǎn)單了很多,一條語(yǔ)句能表示多個(gè)運(yùn)算步驟或者多次寄存器變化,例如自增語(yǔ)句i++,能夠在參加其他運(yùn)算的同時(shí)對(duì)本身值進(jìn)行增加1而又不用增加額外的語(yǔ)句。但是如此精煉的語(yǔ)句卻在實(shí)際生產(chǎn)環(huán)境中會(huì)產(chǎn)生歧義導(dǎo)致嚴(yán)重的后果,這么說并不是說自增語(yǔ)句是洪水猛獸,而是由于C語(yǔ)言應(yīng)用的場(chǎng)景太廣泛,早期發(fā)展標(biāo)準(zhǔn)尚未成形,不同編譯器廠商在語(yǔ)句執(zhí)行順序上尤其是復(fù)雜語(yǔ)句不盡相同,例如自增語(yǔ)句并列使用的時(shí)候,不同編譯器對(duì)它的解析方式會(huì)有不同:(++i)+(++i)+(++i),在不同的編譯器計(jì)算出的結(jié)果是不同的:在VC6.0中結(jié)果為10;在VC2012中結(jié)果為12;在TurboC中結(jié)果是9。那為什么會(huì)出現(xiàn)如此大的結(jié)果差異呢?首先了解一下自增運(yùn)算符的運(yùn)算規(guī)則。

1 自增運(yùn)算符的運(yùn)算規(guī)則

自增運(yùn)算的規(guī)則:自增運(yùn)算符是一元運(yùn)算符,它的作用是使變量的值增1。運(yùn)算符出現(xiàn)在變量的前面稱為前綴運(yùn)算符,運(yùn)算符出現(xiàn)在變量的后面稱為后綴運(yùn)算符。前綴自增運(yùn)算符在程序執(zhí)行過程中遵循“先自增后運(yùn)算”的規(guī)則,后綴自增運(yùn)算符遵循“先運(yùn)算后自增”的規(guī)則。同理,自減運(yùn)算符也是一樣[1]。下面用兩個(gè)簡(jiǎn)單的實(shí)驗(yàn)來實(shí)際運(yùn)行一下自增運(yùn)算符:

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

int main( ){

int a=8,b;

b=a++; /*后綴形式*/

printf(“a=%d, b=%d ”,a,b);

return 0;

}

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

int main( ){

int a=8,b;

b = ++a; /*前綴形式*/

printf(“ a=%d,b=%d”,a,b);

return 0;

}

在實(shí)驗(yàn)1中,b = a++; 相當(dāng)于如下兩條語(yǔ)句:b = a; 和a=a+1; 即先將a的初始值8賦值給b,此時(shí)b的值即為8,然后a自增1。執(zhí)行結(jié)果是:a=9,b=8。

在實(shí)驗(yàn)2中,b = ++a; 相當(dāng)于如下兩條語(yǔ)句:a = a+1; 和 b=a; 即a先做自增1操作,然后再將a自增后的值9賦值給b,此時(shí)b的值即為9。執(zhí)行結(jié)果是:a=9,b=9。

也就是說對(duì)于自增符號(hào)++在變量后面的操作 a++,是先做其他運(yùn)算,再對(duì)a進(jìn)行自增運(yùn)算;而自增符號(hào)++在變量前面的操作++a,是先對(duì)a進(jìn)行自增運(yùn)算,再做其他運(yùn)算[2]。

上面這兩種自增操作,是自增操作的最基礎(chǔ)版本,而在很多教學(xué)資料中會(huì)出現(xiàn)類似于求 (i++)+(i++)+(i++) 、++i * ++i / i++ ; 、 (++i)+(++i)+(++i) 等等計(jì)算結(jié)果的題目分析,由于絕大多數(shù)資料中分析的方法不同,且都從語(yǔ)法的角度來進(jìn)行解析,而非從編譯器的操作流程入手,從而給出的解釋各異,本文就針對(duì)兩個(gè)不同的編譯平臺(tái)對(duì)這段程序進(jìn)行分析。

在當(dāng)前的C語(yǔ)言教學(xué)中,教師們最常用的編譯器是微軟公司出品的VC6.0,VS2012或者更新的版本,而由于編譯器內(nèi)部對(duì)C語(yǔ)言的語(yǔ)法解析有些不同,導(dǎo)致上例:當(dāng)i=1的時(shí)候,(++i)+(++i)+(++i) 在不同的編譯器上得到的結(jié)果完全不同,本文針對(duì)這個(gè)式子,在VC6.0 和 VS2012 兩個(gè)平臺(tái)上的具體計(jì)算過程做一個(gè)對(duì)比。

用來做分析的式子為:(++i)+(++i)+(++i),寫一個(gè)簡(jiǎn)單的示例程序以使其能在上述兩個(gè)編譯器中能運(yùn)行:

int main() {endprint

int i = 1;

int result = (++i)+(++i)+(++i);

printf(“result=%d\n”,result);

return 0;

}

運(yùn)行結(jié)果:

在兩款編譯器中計(jì)算得到的結(jié)果分別是10和12。

接下來在兩款編譯器中分別啟動(dòng)單步調(diào)試,然后右鍵選擇查看反匯編,我們能看到每一條語(yǔ)句在匯編中的執(zhí)行順序是如何的:

首先看示例程序在VC6.0中的解析過程,我們重點(diǎn)看 int result=(++i)+(++i)+(++i);這條語(yǔ)句下面的反匯編代碼:

通過查看上面的反匯編代碼,可以感受到一個(gè)普通的C語(yǔ)言語(yǔ)句:int result=(++i)+(++i)+(++i);在具體的運(yùn)算過程中會(huì)執(zhí)行多少操作,凝練了多少步驟,如果是純粹的機(jī)器語(yǔ)言,步驟還會(huì)更多,從此可見C語(yǔ)言如此精煉。

言歸正傳,我們通過對(duì)上面反匯編代碼的分析,能看出來編譯器是將自增操作執(zhí)行兩次之后(變量i從1變到3),再對(duì)這兩個(gè)數(shù)進(jìn)行了相加運(yùn)算,得到結(jié)果為6,之后再對(duì)變量i做了一次自增操作(變量i從3變到4),再同之前的結(jié)果6進(jìn)行了相加運(yùn)算,結(jié)果為10。

其中[ebp-4] 代表的是變量i,eax、ecx、edx是寄存器,運(yùn)算過程簡(jiǎn)析:

1:將變量i的值存到寄存器eax中,此時(shí)寄存器eax值為1。

2:將寄存器eax中的值加1存到寄存器eax中,此時(shí)寄存器eax值為2 。

3:將寄存器eax中的值傳遞給變量i,此時(shí)變量i的值是2。

4:將變量i的值存放到寄存器ecx中,寄存器ecx此時(shí)為2。

5:將寄存器ecx中的值加1存到寄存器ecx中,此時(shí)寄存器ecx值為3。

6:將寄存器ecx中的值傳遞給變量i,此時(shí)變量i的值是3。

7:將變量i的值存到寄存器edx中,此時(shí)寄存器edx值為3。

8:將變量i的值同寄存器edx中的值相加,存放到寄存器edx中,此時(shí)寄存器edx值為6。

9:將變量i的值存到寄存器寄存器eax中,此時(shí)寄存器eax值為3。

10:將寄存器eax中的值加1存到寄存器eax中,此時(shí)寄存器eax值為4。

11:將寄存器eax中的值傳遞給變量i,此時(shí)變量i的值是4。

12:將變量i的值同寄存器edx中的值相加存放到寄存器edx中,此時(shí)寄存器edx中的值是10。

13:將寄存器 edx中的值傳遞到變量i中,變量i的值為10,最后再賦值給變量result,變量result的值就是10 。

接下來我們看VS2012中是如何解析的:

在int result=(++i)+(++i)+(++i);這條語(yǔ)句下面的反匯編代碼如下:

通過上面反匯編代碼的查看,能看出來編譯器是將自增操作執(zhí)行三次之后(變量i從1變到4),再對(duì)這三個(gè)數(shù)進(jìn)行了相加運(yùn)算,得到結(jié)果為12。

[i]代表的是變量i(同VC6.0中的[ebp–4]是相同的含義),eax、ecx、edx是寄存器,運(yùn)算過程簡(jiǎn)析:

1:將變量i的值存到寄存器eax中,此時(shí)寄存器eax值為1。

2:將寄存器eax中的值加1存到eax中,此時(shí)寄存器eax值為2 。

3:將寄存器eax中的值傳遞給變量i,此時(shí)變量i的值是2。

4:將變量i的值存放到寄存器ecx中,寄存器ecx此時(shí)為2。

5:將寄存器ecx中的值加1存到寄存器ecx中,此時(shí)寄存器ecx值為3。

6:將寄存器ecx中的值傳遞給變量i,此時(shí)變量i的值是3。

7:將變量i的值存到寄存器edx中,此時(shí)寄存器edx值為3。

8:將寄存器edx中的值加1存到寄存器edx中,此時(shí)寄存器edx值為4。

9:將寄存器edx中的值傳遞給變量i,此時(shí)變量i的值是4。

10:將變量i的值傳遞給寄存器eax,此時(shí)寄存器eax值為4。

11:將變量i的值同寄存器eax中的值相加存放到寄存器eax中,此時(shí)寄存器eax的值是8。

12:將變量i的值同寄存器eax中的值相加存放到寄存器edx中,此時(shí)寄存器eax中的值是12。

13:將寄存器eax中的值傳遞到變量result中,變量result的值就是12。

2 結(jié)語(yǔ)

通過前面兩個(gè)實(shí)驗(yàn),我們能看出來,不同版本的編譯器,在匯編的過程對(duì)程序語(yǔ)法做了不同的解析,這個(gè)是我們編程人員無法控制的,并且C語(yǔ)言最主要的應(yīng)用領(lǐng)域就是硬件程序開發(fā)、驅(qū)動(dòng)程序開發(fā)、編解碼、算法優(yōu)化方向的開發(fā),在這些開發(fā)中,由于程序邏輯相對(duì)復(fù)雜,如果我們?cè)诰帉懗绦虻倪^程中過分簡(jiǎn)化程序行數(shù),使用優(yōu)先級(jí)不明確或者是不同編譯器不明確的運(yùn)算方法,會(huì)導(dǎo)致很嚴(yán)重的錯(cuò)誤,類似于上例的程序,在程序出現(xiàn)異常的情況下,開發(fā)人員往往很難定位錯(cuò)誤出現(xiàn)的位置以及原因,會(huì)極大的浪費(fèi)時(shí)間,作為教師應(yīng)該要求學(xué)生養(yǎng)成良好的編程習(xí)慣,用科學(xué)、嚴(yán)謹(jǐn)?shù)膽B(tài)度對(duì)待遇到的問題,在熟練掌握基規(guī)律之后,編寫程序之時(shí),有選擇地小心謹(jǐn)慎地使用自增(自減)運(yùn)算符來簡(jiǎn)化程序,在易錯(cuò)的地方可用其他方法來代替,從而保證程序的執(zhí)行萬無一失[3]。

參考文獻(xiàn)

[1] 張秀建.試析C語(yǔ)言中的自增自減運(yùn)算符[J].電腦編程技巧與維護(hù),2017(11):22-24,64.

[2] 闞鈿玉.C語(yǔ)言中自增(自減)運(yùn)算符號(hào)的應(yīng)用于分析[J].現(xiàn)代計(jì)算機(jī),2016(15):40-43.

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

猜你喜歡
C語(yǔ)言
基于Visual Studio Code的C語(yǔ)言程序設(shè)計(jì)實(shí)踐教學(xué)探索
51單片機(jī)C語(yǔ)言入門方法
基于C語(yǔ)言的計(jì)算機(jī)軟件編程
C語(yǔ)言程序設(shè)計(jì)課程教學(xué)與學(xué)科專業(yè)相結(jié)合的探索
《C語(yǔ)言程序設(shè)計(jì)》翻轉(zhuǎn)課堂教學(xué)改革要點(diǎn)
淺談基于C語(yǔ)言的計(jì)算機(jī)軟件程序設(shè)計(jì)
高職高專院校C語(yǔ)言程序設(shè)計(jì)教學(xué)改革探索
基于C語(yǔ)言的學(xué)生成績(jī)管理系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
基于C語(yǔ)言的常用排序算法比較研究
論子函數(shù)在C語(yǔ)言數(shù)據(jù)格式輸出中的應(yīng)用
尤溪县| 长兴县| 隆子县| 特克斯县| 太保市| 洛阳市| 张北县| 平江县| 卢龙县| 永福县| 贵德县| 丹江口市| 陇西县| 五原县| 桑植县| 镇原县| 涿州市| 九台市| 扎赉特旗| 铜梁县| 四川省| 双峰县| 尚志市| 贵定县| 大英县| 郯城县| 镶黄旗| 永寿县| 南乐县| 棋牌| 株洲市| 长泰县| 宁夏| 梧州市| 阳山县| 上虞市| 陕西省| 长泰县| 滕州市| 仲巴县| 大姚县|