闞鈿玉(廣東南方職業(yè)學(xué)院信息技術(shù)系,江門 529040)
?
C語言中自增(自減)運(yùn)算符的應(yīng)用與分析
闞鈿玉
(廣東南方職業(yè)學(xué)院信息技術(shù)系,江門529040)
摘要:
關(guān)鍵詞:
C語言;運(yùn)算符;自增(自減)運(yùn)算符
C語言程序設(shè)計(jì)中,若合理使用自增(自減)運(yùn)算符,則可以減少代碼編寫,提高編程效率;若不能正確掌握和運(yùn)用,則容易出錯(cuò)[1]。通常初學(xué)者對自增(自減)運(yùn)算符很是費(fèi)解,但是,在C語言的眾多教材和參考書中,對C語言中的自增(自減)運(yùn)算符介紹非常簡略,而實(shí)踐操作中,使用頻率較高,教學(xué)中,有必要對其進(jìn)行詳細(xì)分析,讓學(xué)生理解并掌握不同使用形式中的不同解題思路和方法。
通常C語言教材中把自增(自減)運(yùn)算符歸納于算是運(yùn)算符中,其符號(hào)分別為“++”或“--”,
其作用是使變量的值自己增1或減1,而運(yùn)算結(jié)果仍保存在該變量的存儲(chǔ)單元中,所以通常也稱為增1或減1運(yùn)算符[2]。自增(自減)運(yùn)算符的操作對象只能是變量,而不能是常量或表達(dá)式,例如:m++、k--是合法的,而3++、(a+b)--是非法的,因?yàn)槌A康闹禑o法改變,所以不能自增1,若是表達(dá)式(a+b)--,假如a+b=7,自減后的值為6,而6是保存在a的存儲(chǔ)單元中還是保存在b的存儲(chǔ)單元中呢?無法確定,所以(a+b)--是非法的[1]。
自增(自減)運(yùn)算符有兩種形式:一種“++”或“--”在變量之前,稱為前置運(yùn)算,如++a;
一種是“++”或“--”在變量之后,稱為后置運(yùn)算,如b--[2]。前置后后置兩種不同的表示方法最終會(huì)使自增(自減)運(yùn)算方式不同,++a或--a指在使用之前先是a的值加1或減1,然后再參與別的運(yùn)算,即“先變后用”;a++或a--指先用a原來的值去參與運(yùn)算,然后再是a的值加1或減1,即“先用后變”[3]。當(dāng)自增(自減)表達(dá)式作為單一語句出現(xiàn)時(shí),二者沒有區(qū)別,但把它們引用在表達(dá)式中則有明顯區(qū)別。例如:
(1)a=m++,等價(jià)于:a=m;m=m+1;如果開始m=3,則執(zhí)行a=m++后,a=3,m=4。
(2)a=++m,等價(jià)于:m=m+1;a=m;如果開始m=3,則執(zhí)行a=++m后,a=4,m=4。
自增(自減)運(yùn)算符是單目運(yùn)算符,優(yōu)先級(jí)為2,高于其他的雙目運(yùn)算符和三目運(yùn)算符的優(yōu)先級(jí),但其結(jié)合性為右結(jié)合,即是按照“自右向左”的順序來進(jìn)行運(yùn)算的。例如:
#include<stdio.h>
main()
{int m,n=5;
m=-n++;
printf(“m=%d,n=%d”,m,n);
}
此例m=-n++表達(dá)式中,程序是執(zhí)行m=(-n)++,還是執(zhí)行m=-(n++)呢?遇到運(yùn)算符,我們就從“優(yōu)先級(jí)”和“結(jié)合性”這兩方面分析,這里“-”負(fù)號(hào)運(yùn)算符和“++”自增運(yùn)算符的優(yōu)先級(jí)都是2,結(jié)合性都是右結(jié)合,C語言中規(guī)定:相同優(yōu)先級(jí)的運(yùn)算符的運(yùn)算次序由結(jié)合性決定。而這兩個(gè)運(yùn)算符的結(jié)合性都是有結(jié)合,那么表達(dá)式m=-n++應(yīng)該理解為m=-(n++),所以此程序的運(yùn)行結(jié)果為:m=-5,n=6。對于初學(xué)者來說,編程是可以多加括號(hào)來避免出錯(cuò)。
大部分學(xué)生在學(xué)習(xí)自增(自減)運(yùn)算符時(shí),都能夠理解前置運(yùn)算是“先變后用”,而后置運(yùn)算是“先用后變”的運(yùn)算規(guī)則,但當(dāng)遇到具體實(shí)例或比較復(fù)雜的運(yùn)算表達(dá)式時(shí),則不知所措,很難靈活運(yùn)用“先變后用”或“先用后變”這個(gè)規(guī)則,下面以實(shí)例逐一分析。
2.1自增(自減)運(yùn)算符組在的復(fù)雜表達(dá)式語句中的應(yīng)用
大家知道,C程序中計(jì)算模塊的代碼大部分由表達(dá)式語句組成,而這些表達(dá)式就是運(yùn)算符和操作數(shù)連接起來的式子。我們在計(jì)算這些表達(dá)式時(shí)要從運(yùn)算符的“優(yōu)先級(jí)”和“結(jié)合性”這兩方面討論,自增(自減)運(yùn)算符是單目運(yùn)算符,優(yōu)先級(jí)為2,而且是右結(jié)合,那么,在復(fù)雜表達(dá)式中,我們怎么運(yùn)用“先變后用”和“先用后變”這個(gè)原則呢?
例1閱讀以下程序,分析運(yùn)行結(jié)果
#include<stdio.h>
void main()
{int m,n=8;
m=(n++)+(n++)+(n--);
printf(“m=%d,n=%d ”,m,n);
n=8;
n=(n++)+(n++)+(n++);
printf(“n=%d ”,n);
n=8;
m=(++n)+(++n)+(--n);
printf(“m=%d,n=%d ”,m,n);
n=8;
n=(++n)+(++n)+(--n);
printf(“n=%d ”,n);
}
分析:第4行m=(n++)+(n++)+(n--)中,由于自增(自減)運(yùn)算符是后置運(yùn)算,應(yīng)執(zhí)行“先用后變”的原則,則m=8+8+8=24,然后n的值在自增兩次,自減1次,即n=8+1+1-1=9;這里很多初學(xué)者誤解為m=8+8+ 10=26,我們一定要深入理解“先用后變”這個(gè)原則,雖然m=(n++)+(n++)+(n--)中前面兩個(gè)n++相加得18,此時(shí)“先用后變”中的“用”還沒用完,所以n的值不能改變,我們應(yīng)該理解為m=8+8+8=24,所以第5行輸出的結(jié)果為:m=14,n=9。
第7行n=(n++)+(n++)+(n--)中也是后置運(yùn)算,道理與第4行代碼相同,只是此時(shí)左邊變量是n而不是m,所以計(jì)算出來的n=24后再自增2次,自減1次,則n=24+1+1-1=25,所以第6行的輸出結(jié)果為n=25。
第10行m=(++n)+(++n)+(--n)中,由于前置運(yùn)算,應(yīng)該執(zhí)行“先變后用”的原則,而內(nèi)存是從左至右掃描,在VC6.0中,內(nèi)存是掃描一段就計(jì)算一段,所以n應(yīng)先自增兩次變?yōu)?0再相加,即m=10+10+(--n)=20+ (--n),然后n再先自減變?yōu)?,最后再參與算術(shù)“加法”運(yùn)算,即m=20+9=29,所以第11行輸出的結(jié)果為:m=29,n=9。第13行n=(++n)+(++n)+(--n)中,運(yùn)算原理與第10行相同,只是左邊的變量由m換成了n,所以第14行輸出的結(jié)果為n=29。
例2閱讀以下程序,分析運(yùn)行結(jié)果
#include<stdio.h>
void main()
{int a,b,c;
a=b=c=1;
++a&&--b&&++c;
printf(“a=%d,b=%d,c=%d ”,a,b,c);
a=b=c=0;
++a||++b&&++c;
printf(“a=%d,b=%d,c=%d ”,a,b,c);
}
此例第5行表達(dá)式++a&&--b&&++c中有自增(自減)運(yùn)算符和邏輯運(yùn)算符,而自增(自減)運(yùn)算符的優(yōu)先級(jí)高于邏輯符,所以應(yīng)該計(jì)算++a和--b,得出2&&0&&++c;此時(shí)要注意C語言中邏輯與和邏輯或運(yùn)算都有短路特性,即如果在一個(gè)復(fù)雜的表達(dá)式中前一部分的值能夠決定整個(gè)表達(dá)式的值,那么后面的表達(dá)式則不進(jìn)行掃描計(jì)算,在2&&0&&++c中,無論++c的值是多少,表達(dá)式2&&0&&++c的值都是0,后面的++c沒被執(zhí)行,所以第6行的輸出結(jié)果為:a=2,b=0,c=1。第9行表達(dá)式++a||++b&&++c中,由于計(jì)算機(jī)是從左只有掃描的,所以先執(zhí)行++a得出1,此時(shí)表達(dá)式為1||++ b&&++c,而此表達(dá)式無論++b&&++c的結(jié)果是多少,整個(gè)表達(dá)式1||++b&&++c的值始終是1,后面的++b 和++c不被執(zhí)行,b,c的結(jié)果還是1,所以第10行的輸出結(jié)果為:a=1,b=0,c=0。
2.2自增(自減)運(yùn)算符在循環(huán)結(jié)構(gòu)中的應(yīng)用
C語言中的循環(huán)結(jié)構(gòu)有三種語句:while語句,do……while語句,for語句。無論哪種循環(huán)語句,都必須有改變循環(huán)變量而使循環(huán)條件不成立的語句,而這樣的語句經(jīng)常是循環(huán)變量自增(自減)表達(dá)式語句,若i為循環(huán)變量,則經(jīng)常被用來使循環(huán)趨于結(jié)束的語句是i++或i--,最常見的for語句就是這樣的,例如for(i=1,s=1;i<=10;i++)s=s*i;當(dāng)i=11時(shí),循環(huán)條件不成立,循環(huán)結(jié)束,所以在循環(huán)結(jié)構(gòu)中,自增(自減)運(yùn)算符一般是改變循環(huán)變量的作用。
2.3自增(自減)運(yùn)算符在printf()函數(shù)中的應(yīng)用
在VC6.0運(yùn)行環(huán)境下,printf()函數(shù)執(zhí)行過程是將函數(shù)實(shí)際參數(shù)表達(dá)式的值按照從右至左的順序入棧,入棧前就將printf()函數(shù)實(shí)際參數(shù)表達(dá)式的值計(jì)算完畢,被調(diào)函數(shù)從棧中取出參數(shù)使用,如果printf()函數(shù)有多個(gè)參數(shù),則它們是按照從右至左的順序計(jì)算,但是printf()函數(shù)輸出結(jié)果的順序仍是從左至右,與計(jì)算機(jī)掃描順序一致。
例3閱讀以下程序,分析運(yùn)行結(jié)果
#include<stdio.h>
void main()
{int i=8;
printf(“%d,%d,%d,%d,%d,%d ”,i++,i++,i++,i++,i++,i++);
printf(“%d ”,i);
i=8;
printf(“%d,%d,%d,%d,%d,%d ”,++i,++i,++i,++i,++i,++i);
printf(“%d ”,i);
}
第4行代碼中,printf()函數(shù)的輸出表列是多個(gè)表達(dá)式,而且都是自增運(yùn)算符的后置運(yùn)算,還是遵循“先用后變”的原則,只是這里的“先用”是一直計(jì)算完printf()函數(shù)的所有輸出列表,“后變”則是指printf()函數(shù)輸出結(jié)果后再改變i的值,所以第4行的輸出結(jié)果為:8,8,8,8,8,8。而第5行i的值應(yīng)是從8自增6次后的值14,所以第5行的輸出結(jié)果為14。第7行代碼中,printf()函數(shù)的輸出表列是多個(gè)前置運(yùn)算表達(dá)式,我們遵循“先用后變”的原則,但這時(shí)要注意printf()函數(shù)的計(jì)算參數(shù)順序是從右至左,而輸出時(shí)則是從左至右輸出,所以第7行輸出結(jié)果是:14,13,12,11,10,9。第8行輸出結(jié)果為14。
從這個(gè)例子分析得出:printf()函數(shù)的參數(shù)中若有自增(自減)運(yùn)算符的表達(dá)式,我們一定要注意:若是前置運(yùn)算,例如i++或i--時(shí),i的值是在printf()函數(shù)執(zhí)行之后才被刷新,所以在printf()函數(shù)中,i++或i--對i的值暫時(shí)不產(chǎn)生影響;若是前置運(yùn)算,例如++i或--i時(shí),i的值在printf()函數(shù)執(zhí)行之前改變,但計(jì)算順序是從右至左,輸出時(shí)仍按從左至右輸出結(jié)果。
2.4自增(自減)運(yùn)算符在指針中的應(yīng)用
C語言中規(guī)定,當(dāng)指針p指向一串連續(xù)的存儲(chǔ)單元時(shí),可以對指針p進(jìn)行自增或自減運(yùn)算,這種操作稱為指針的移動(dòng),例如p++或p--,都可以使指針移動(dòng),p++是表示指針下移一個(gè)數(shù)據(jù),即指向下一個(gè)元素,p--是表示指針上移一個(gè)數(shù)據(jù),即指向上一個(gè)元素,而不是將p的值直接增1或減1,既然是表示指向下一個(gè)元素或上一個(gè)元素,那么就要求這一系列元素必須在內(nèi)存中連續(xù)存儲(chǔ),所以通常p++或p--只能在數(shù)組中討論,而且我們還要小心p++,p--不能超出數(shù)組的上下限[4]。
例4閱讀以下程序,分析運(yùn)行結(jié)果
#include<stdio.h>
void main()
{int *p,a[10]={1,2,3,4,5,6,7,8,9,10};
for(p=&a[9];p>=a;p--)
printf(“%d,”,*p);
}
第4代碼中,p的初值是指向a[9]這個(gè)元素,然后輸出a[9],接著p指向上一個(gè)元素a[8],然后又輸出a [8],直到輸出a[0]為止,所以以上程序結(jié)果為:10,9,8,7,6,5,4,3,2,1。
自增(自減)運(yùn)算符在C語言編程過程中運(yùn)用頻率很高,對于初學(xué)者來說既是重點(diǎn)又是難點(diǎn),在不同的使用形式中,分析思路略有不同,要求使用者倍加小心,靈活運(yùn)用。
參考文獻(xiàn):
[1]周偉.C語言中自增(自減)運(yùn)算符教學(xué)探究[J].軟件導(dǎo)刊,2012(12).
[2]董漢麗.C語言程序設(shè)計(jì)[M].第6版.大連:大連理工出版社,2013.
[3]李彩玲.C語言中自增自減運(yùn)算符的應(yīng)用與解析[J].晉城職業(yè)技術(shù)學(xué)院學(xué)報(bào),2013(3).
[4]譚浩強(qiáng).C程序設(shè)計(jì)[M].第4版.北京:清華大學(xué)出版社,2010.
The operators of C language are rich,its increment(decrement)operator is distinctive and frequently used in C language,for new leaners and beginners,it is most difficult part to get understood and easy to make mistake.Considering the basic characteristics of the increment (decrement)operator,and followed by many years of experience from teaching and practical application in VC6.0 environment,start from the real and alive example,go through from easy to difficult and step by step,and summarize a variety of different solving problem solution,which can bring the help to new leaners and beginners great help to understand and know well of increment(decrement)operator.
Keywords:
C Language;Operators;Increment(Decrement)Operators
Application and Analysis of Increment(Decrement)Operator in C Language
KAN Tian-yu
(Department of Information Technology,Guangdong Nanfang Vocational College,Jiangmen 529000)
Abstract:
C語言中運(yùn)算符非常豐富,自增(自減)運(yùn)算符是C語言中比較有特色而且使用頻率較高的運(yùn)算符之一,對于初學(xué)者來說,也是最難理解而又最容易出錯(cuò)的運(yùn)算符。根據(jù)自增(自減)運(yùn)算符的基本特點(diǎn),再結(jié)合多年教學(xué)和使用經(jīng)驗(yàn),以VC6.0為運(yùn)行環(huán)境,從示例入手,由淺入深,總結(jié)出多種不同使用形式中的不同解題思路,希望為初學(xué)者學(xué)習(xí)自增(自減)運(yùn)算符帶來幫助。
文章編號(hào):1007-1423(2016)15-0040-04
DOI:10.3969/j.issn.1007-1423.2016.15.011
作者簡介:
闞鈿玉(1979-),女,湖北通山人,碩士,研究方向?yàn)檐浖こ?、電子商?wù)及高職教育學(xué)理論
收稿日期:2016-03-15修稿日期:2016-05-10