序列點在C語言運算式求值中的作用

來源:互聯網
上載者:User

標籤:c   序列點   

摘要:

本文開創性地分析了序列點在C語言運算式求值中的作用:序列點左邊的運算元要先於其右邊的運算元求值。討論了逗號操作符,、邏輯與操作符&&、邏輯或操作符||和條件操作符?:的問號處需要序列點的原因。舉例分析了序列點在運算式求值中的作用。

關鍵字:序列點 運算式求值 C語言

C語言作為一種主流程式設計語言,許多程式設計語言如Java、C++、C#都借鑒了它的文法。C語言也是一種很適當的程式設計入門的教學語言,國內大專院校的許多專業都開設了這門課程並且大多將其作為第一門程式設計語言課程,同時C語言也是全國電腦等級考試二級的內容。因此,C語言的教學品質對學生的後續學習和取得等級認證很重要,尤其是對學生在實際工作中更好地瞭解和使用電腦有非常重要的意義。

目前,國內絕大多數教材在介紹C語言運算式時,都沒有介紹C語言的一個重要概念——序列點[1]。序列點概念的缺失使得讀者只能記憶而不是遵循求值規則分析有序列點運算式的求值順序。以簡單的逗號運算式a = 3, ++a為例,設變數a為整型變數(下面運算式中出現的變數也預設為整型)。“逗號運算式自左向右依次求值”,故先對子運算式a = 3求值,再對子運算式++a求值。在實際教學中善於質疑的學生往往會問:運算式中自增操作符++的優先順序最高,為何要先求子運算式a=3的值?運算式求值時不是先算高優先順序的操作符嗎?運算式究竟有沒有求值原則呢?這不僅使得學生對C語言知識的認知殘缺不全,而且也影響了學生自主學習的積極性,不利於創新型人才的培養。

一、序列點的定義及分析

根據C語言標準[2],序列點就是執行序列中的一些特定點,在這些點上,前面求值的副效應(side effect)應徹底完成且其後求值的副效應均未發生。在教材中照搬標準讓初學者學習理解序列點是不明智的,應直接向初學者指出序列點在運算式求值中起的作用。含有序列點的運算式求值時要保證有序列點的操作符左邊的由子運算式構成的運算元先於其右邊的運算元求值[3]。C語言運算式求值的原則為:先考慮序列點,再根據操作符的優先順序和結合性求值。

運算元是指操作符的操作對象,如運算式3+2中加法操作符左邊的運算元為3,右邊的運算元為2。在複雜的運算式中,需結合操作符的優先順序和結合性來確定某操作符的運算元。對於運算式3+2*5,加法操作符左邊的運算元為3,但其右邊的運算元不為2,進行加法運算時3顯然不可能和2相加。因為與加法操作符右邊相鄰的操作符為乘法操作符,其優先順序較高,所以加法操作符右邊的運算元為2*5(的積)。而乘法操作符左邊的運算元為2,右邊的運算元為5。對於運算式3+2-5,加法操作符右邊相鄰的操作符為減法操作符,兩者優先順序相同,但結合性為左結合,故它右邊的運算元為2。

運算式a = 0 && ++a中邏輯與左邊的運算元為0,右邊的運算元為子運算式++a,整個運算式為賦值運算式;而運算式(a = 0) && ++a中邏輯與左邊的運算元為子運算式(a = 0),右邊的運算元為子運算式++a,整個運算式為邏輯運算式。邏輯與操作符有序列點,因此運算式(a = 0) && ++a求值時,雖然自增操作符的優先順序最高,但求值時首先考慮序列點,邏輯與操作符左邊的運算元(a = 0)需先於其右邊的運算元++a求值。

二、C語言中部分操作符需要序列點的原因

逗號操作符(,)有序列點。逗號操作符多用於把多條語句變成一條語句,如a = 2;和++a;為兩條語句,而a = 2, ++a;是一條語句。語句a = 2, ++a;執行時,如果逗號操作符沒有序列點,子運算式++a就會先執行,即這條語句的執行順序與上面兩條語句的並不相同。基於逗號操作符的作用,逗號操作符只能優先順序最低,且含有序列點。

邏輯與操作符(&&)有序列點。C語言中邏輯與操作符實行“短路計算”,即當其左邊的運算元值為0即假時,不對右邊的運算元求值而直接把0(假)作為求值的最終結果。如果邏輯與操作符沒有序列點,運算式3>5 && ++a求值時,自增操作符的優先順序最高,子運算式++a應先求值。邏輯與操作符左邊的運算元3>5求值的結果為0,即假,根據短路計算,作為邏輯與右邊的運算元,子運算式++a不會被求值。顯然兩者矛盾。為了短路計算,邏輯與操作符&&需要序列點。有了序列點之後,求值時序列點左邊的運算元將先於其右邊的運算元求值,即子運算式3>5先求值,由於短路計算,整個運算式的值為0,即假,且右運算元子運算式++a不會被求值。

邏輯或操作符(||)有序列點。C語言中邏輯或操作符也實行“短路計算”,因此,其有序列點的必要性與邏輯與操作符的相同。

條件操作符?:的問號處?有序列點。條件操作符常用於改寫簡單的if-else選擇結構,如下面的語句

if(a > b)

       ++a;

else

       ++b;

可用條件操作符改寫為a > b ? ++a : ++b;。

如果條件操作符沒有序列點,語句a > b ? ++a : ++b;執行時,++a和++b會先於子運算式a > b執行,這樣的執行順序顯然與if-else選擇結構的不同,因此,條件操作符?:的問號?處有序列點。語句a > b ? ++a : ++b;執行時,問號處?左邊的運算元a > b先執行,值為真時,對++a求值,不對++b求值;值為假時,反之。

三、含有序列點的運算式的求值分析

       設整型變數a的值為0。對於運算式‘a‘ || (a = 1) && (a += 2),邏輯或||左邊的運算元為‘a‘,右邊的運算元為(a = 1) && (a += 2);邏輯與&&左邊的運算元為(a = 1),右邊的運算元為(a += 2)。求值時首先考慮序列點,邏輯或左邊的運算元‘a‘的值非“0”為真,執行短路計算,其右邊的運算元不會被求值,因此,整個運算式的值為1,即真。在運算式求值的過程中,變數a的值沒有改變。

對於運算式(a = 0) && (a = 5) || (a += 1),邏輯與&&左邊的運算元為(a = 0),右邊的運算元為(a = 5);邏輯或||左邊的運算元為(a = 0) && (a = 5),右邊的運算元為 (a += 1)。求值時首先考慮序列點,邏輯與&&左邊的運算元(a = 0)先求值,求值時一方面變數a的值會變成0,另一方面這個子運算式的值為0即假,執行短路計算,其右邊的運算元(a = 5)不會被求值,因此,原運算式變為0 || (a += 1)。邏輯或||左邊的運算元值為0,即假,不能短路計算,只能再求其右邊運算元的值。子運算式(a += 1)求值時一方面變數a的值由0變成1,另一方面這個子運算式的值為1即真,因此,原運算式的值為1,即真。運算式的求值完成後,變數a的值變為1。

特彆強調,用賦值運算式作為邏輯操作符的運算元僅僅為了清晰地表明在運算式求值過程中某個子運算式是否被求值,這類運算式的實用性和可讀性非常差,實際編程時最好不要用賦值運算式做運算元。

       序列點不僅可以使低優先順序的操作符先於高優先順序的操作符求值,而且也可以影響操作符的結合性。運算式a > b ? ++a : c > d ? ++c : ++d有兩個條件操作符,條件操作符為右結合,因此,原運算式的求值順序應為(a > b ? ++a : (c > d ? ++c : ++d))。左邊條件操作符的3個運算元分別為子運算式a > b,子運算式++a和子運算式c > d ? ++c : ++d。按照結合性,子運算式(c > d ? ++c : ++d)應先求值,但是,由於左邊條件操作符的問號處?有序列點,故子運算式a >b先求值,如果其為真,則只會對子運算式++a求值,而不會再對子運算式c > d ? ++c : ++d求值了。顯然,此運算式中條件操作符的右結合只用於確認左邊條件操作符的右運算元,而沒有使得右邊條件操作符先求值。

四、結束語

雖然C語言運算式種類繁多,但有著相對明確的運算式求值規則,根據求值規則正確分析出運算式的求值順序有助於激發學生學習的主動性。在教材中照搬C語言標準中序列點的概念勢必會增加學習的難度,給初學者提供一個準確且易於理解的概念,不僅不會造成C語言知識點的殘缺,而且也為啟發學習法教學提供了可能。

參考文獻

[1]黃瑛,胡烈,朱其慎. 序列點——C語言教學的一個普遍盲區[J].電腦知識與技術,2011(3):2105-2106.

[2]國家技術監督局. GB/T 15272-1994 程式設計語言C[S]. 北京:中國標準出版社,2004.

[3]周二強著. C語言內涵教程[M]. 中國鐵道出版社,2013:68.

Effect of Sequence Point on Expression Evaluation in Language C

Abstract:

The effect of the sequence point on expression evaluation in Language C is analyzed from all new angle of view. The operand in the form of sub-expression located to the left of the operator with sequence point is evaluated before the right operand. This text explains the reason the comma operator, logical AND operator, logical OR operator and ternary conditional operator need sequence points. The role of the sequence point on expression evaluation is discussed by citing examples.

Keywords: sequence point; expression evaluation; language C


序列點在C語言運算式求值中的作用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.