夏超群
(武漢工程職業(yè)技術學院江北校區(qū) 湖北 武漢:430415)
C語言的運算符非常豐富,在程序中可以靈活使用它們以達到所需的功能。許多初學者學習使用過程中,經(jīng)常對自增、自減運算符的運算結果產(chǎn)生質(zhì)疑,弄懂自增、自減運算符的運算,顯得至關重要。
它是單目運算符,其功能是使操作數(shù)的值增1。其操作數(shù)必須為變量,++可以置于操作數(shù)前面,也可以放在后面。例如:
++n ;n++ ;
這兩個語句執(zhí)行的結果都是使變量n的值增加1,單純從這兩個語句的執(zhí)行結果上看++前置和后置似乎沒有區(qū)別,它們和下面的賦值語句得到的效果也是一樣:
n=n+1;
但我們不應該被表象迷惑,實際上,++前置和后置是有區(qū)別的,具體如下:
n++:先使用n的值,再使n值增加1。
++n:先使n值增加1,再使用n的值(使用時n的值已經(jīng)增加了)。
例如:int n=1,p,q;
p=n++;q=++n;
對于“p=n++;”這個語句,是先使用n的值,將其賦給p,再使n的值增加1。即該語句等價于這樣兩條語句:p=n;n=n+1;所以這個語句執(zhí)行完后,p的值是1,而n的值變成2。對于“q=++n;”這個語句,是先使n的值增加1,再將n的值賦給q。即該語句等價于這樣兩條語句:n=n+1;q=n;所以這個語句執(zhí)行完后,n的值變?yōu)?,而q的值也是3。
無論前置還是后置,++都會使其操作數(shù)的值增1。不同的是,++前置(如++n)時,自增表達式的值等于其操作數(shù)自增后的值;++后置(如n++)時,自增表達式的值等于其操作數(shù)自增前的值。
例如:int n=5,p=0,q=0;
q=++n+q;//該語句執(zhí)行后q為6,n為6
n=5;
p=n+++p;//該語句執(zhí)行后p為5,n為6
上例中,表達式++n的值等于n自增后的值,即6,所以q最后得到的值為6。表達式n++的值等于n自增前的值,即5,所以p最后得到的值為5。
自減運算符的功能及應用類似于自增運算符, --的操作數(shù)也必須為變量。--可置于操作數(shù)前面,也可置于操作數(shù)后面。區(qū)別只在于自減運算符使操作數(shù)的值減1,而自增運算符使操作數(shù)的值增1。具體如下:
--n:先使n值減1,再使用n的值(使用時n的值已經(jīng)減少了)。
例如:int n=5,p=0,q=0;
q=--n+q;//該語句執(zhí)行后q為4,n為4
n=5;
p=n--+p;//該語句執(zhí)行后p為5,n為4
不管是自增還是自減,前置運算符是“先變后用”,如++n或--n,執(zhí)行后表達式的值和變量n的值相同;而后置運算符是“先用后變”,如n++或n--,執(zhí)行后表達式的值和變量n的值不同。
Android系統(tǒng)中含有很多涉及獲取用戶隱私的API(Sources點)以及隱秘的數(shù)據(jù)發(fā)送途徑(Sinks點),通過歸類整理并使用基于過程間數(shù)據(jù)流分析技術[5]的污點傳播算法,尋找從Sources點到Sinks點的傳播路徑,從而發(fā)現(xiàn)這些隱私泄露問題。
自增運算符和自減運算符的優(yōu)先級比+-*/的優(yōu)先級要高。因此“n*m++”表示“n*(m+ +)”,而不是“(n*m)++”。而且“(n*m)++”是錯誤的使用方式。因為++和--的操作數(shù)只能是變量,不能是表達式或常量,而“n*m”是表達式。
注意,不要把優(yōu)先級和運算順序混淆了。
例如:int x=1,y=2,z;
z=(x+y++)*3;//該語句執(zhí)行后z值為9, y值為3
用數(shù)字代替上面的語句得:z=(1+2)*3;
優(yōu)先級表明的是++作用于y,而不是(x+y),但它決定不了y的值何時增1。我們可以肯定的是,在整個語句執(zhí)行完畢后,y的值肯定增加了。但是,我們不知道該語句執(zhí)行中的什么時候,y的值會增1,這是由編譯器決定的。
C語言表達式的應用非常靈活,這種靈活性可使C程序簡潔,但同時也會引起副作用:使程序費解,分析程序時易于發(fā)生誤解或錯誤。而且C語言發(fā)展至今,不同的軟硬件環(huán)境有不同版本的編譯軟件,對同一個C的源程序,不同軟硬件環(huán)境、不同的編輯編譯軟件處理的結果不同。由于現(xiàn)在一般都是使用圖形界面的操作系統(tǒng),使用的編譯軟件也是簡單直觀的圖形界面為主,下面以VC++6.0環(huán)境C程序中自增、自減運算符的應用來進行詳細分析。
例1:分析下面程序運行后的輸出
分析:由于單目運算符的優(yōu)先級高于雙目運算符,而且自增自減運算符的結合性是自右至左的,所以程序的4、6、8行的語句分別等價于:a=(++b)+ (c--);a=(b--)-c;a=-(b++)+c;我們前面說過自增自減符前置時是“先變后用”,執(zhí)行后表達式的值和變量的值相同;后置時是“先用后變”,執(zhí)行后表達式的值和變量n的值不同。
由此分析知:第4行語句執(zhí)行情況為:表達式+ +b的值為6,變量b的值為6;表達式c--的值為5,變量c的值為4;所以a=6+5。
同理,第6行語句執(zhí)行情況為:表達式b--的值為6,變量b的值為5;所以a=6-4。第8行語句執(zhí)行情況為:表達式b++的值為5,變量b的值為6;所以a=-5+4。所以程序運行的輸出如圖1所示。
圖1 例1在VC++6.0下的運行結果
例2:分析下面程序運行后的輸出
分析:該例4、5行語句中各有若干個自增表達式,從理論上分析第4行語句中表達式(i++)+(i+ +)+(i++)的值應為5+6+7,實際卻是不論何種編譯器執(zhí)行結果都是5+5+5,這說明后置自增自減運算符的“先用后變”的“變”是指在下一條語句執(zhí)行前統(tǒng)一改變,而不是剛用完就變,故第4行語句等價于:p=i+i+i;i=i+1;i=i+1;i=i+1;
第5行語句執(zhí)行結果和所用的編譯器有關,由于我們前面已經(jīng)說明在VC++6.0環(huán)境下分析運算符運算結果,因此該語句等價于:j=j+1;j=j+1; q=j+j;j=j+1;q=q+j;
造成這種結果是因為高級語言的一條語句經(jīng)編譯解釋成若干條機器指令,這若干條機器指令的順序最終決定該等價高級語言語句的執(zhí)行結果。
該例是教學時所用教材上的實例,教材上分析認為運行輸出如圖2所示,教材上并未說明該結果是在何編輯環(huán)境下的輸出。我校機房運行調(diào)試C程序用的是VC++6.0,為了讓學生能理解運行環(huán)境對結果的影響,我特意讓學生上機運行這個程序,結果輸出如圖3所示。
圖2 例2在TC下的編譯輸出
圖3 例2在VC++6.0下的編譯輸出
為了讓學生分析該例第5行為什么會得到非預期或者說與教材不同的結果,將該例代碼稍作修改后以c1.c為文件名保存,同時為學生提供不同的編輯編譯環(huán)境,讓學生分別在不同編譯環(huán)境中調(diào)試運行該程序,并分析得到這種運行結果的原因。通過自己動手上機調(diào)試分析,學生很容易理解自增、自減運算符前后置時運行結果為何不同。
文件名為c1.c的源代碼如下:
例3:分析下程序運行后的輸出。
分析:由上兩個程序的分析知:后置自增或自減運算符時,自增或自減變量值是在本語句執(zhí)行后,下一語句執(zhí)行前改變。因此有:表達式x++的值為17 (先用),表達式—y的值為4,y值也為4,17/4結果取整為4,x=17*4。第4行語句執(zhí)行后再執(zhí)行表達式x++的變(后變),程序的運行結果如圖4所示。
圖4 例3在VC++6.0下的編譯輸出
C語言運算符的靈活應用可能會讓初學者對程序造成誤解,甚至不明白程序為何得到此種結果。學習程序關鍵在于多分析、多設計程序,程序的運行一定會遵循某一規(guī)律。而對于自增自減運算符來說,都知道運算符后置時是先用后變,但相關變量的值何時變才是關鍵,要明白這一點,就需要在實踐中理解掌握。如果通過實踐明白的先用后變的“變”是在下一語句執(zhí)行前進行的,那么再錯綜復雜的運算符的應用,分析它的運算結果也得心應手了。
[1] 譚浩強.C程序設計[M].北京:清華大學出版社.
[2] 陽曉霞,劉清華.C語言教學探討——易造成學生困惑的幾種運算符[J].福建電腦,2007,(11):212-214.
[3] 吳 瓊.C語言運算符的結合性分析[J].電腦知識與技術, 2007,(2):463-464.