2013-03-26 43 views
3

在我對一個問題here的回答中,我解釋了在與語句return同一行上的全局變量上使用postfix ++時發生的情況。返回語句後的序列點?

C11的信息性附錄C指出緊接在return之後有一個序列點,並且涉及規範性章節6.8.6.4,其中沒有找到關於序列點的文本。

在C標準中,我可以找到規範性文本,說明在return陳述後面有一個序列點?

(我只找到規範文本,說明這個庫函數,作爲一個特殊的情況下,在7.1.4/3)

回答

4

Ç2011(草案n1570)6.8 4:「每個下面的是一個完整的表達式:... 返回聲明中的(可選)表達式。有一個完整的表達式的評價和未來充分表達進行評估的評估之間的序列點。」

所以技術上的序列點不是回報後反而是表達的評價之間返回和下一個表達式。考慮下面的代碼,當調用a最初0:

int a = 0; 

int Foo(void) { return a++; } 

void Bar(void) 
{ 
    int b = Foo() + a; 
    … 
} 

Foo() + a,是否Foo()a首先計算是不確定的。我們將根據兩個潛在規則(返回之後的序列點相對於返回的表達式與下一個完整表達式之間的序列點)來考慮這兩個訂單。如果實現不a第一,那麼就必須做到:

a 
Sequence point 
Foo() 
+ 

,然後其他一些充分表達會跟進,因此,通過任何規則,將有一個序列點,這個代碼是相同的無論哪種方式,就我們而言。其結果是,b設置爲0

如果實現不Foo()第一,然後與規則「一回報後序列的指針」,實現必須做到:

Sequence point 
Foo() 
Sequence point 
a 
+ 

此代碼將具有定義的行爲:aFoo中增加副作用,並且在訪問a之前完成,然後執行+。結果是a被設置爲1.雖然結果可以是0或1,但是該「在返回」之後的序列點「規則,其僅僅是未指定使用兩個訂單中的哪一個;行爲並不完全未定義。

但是,如果執行不Foo()第一和使用的標準C規則「序列點的回報表達和下一個完整表達的」,那麼我們有:

Sequence point 
Foo() 
??? 
a 
??? 
+ 
??? 

的「 ???「標記所需序列點可能位於的地方 - 在返回之後和下一個完整表達式之前的任何地方。在這種情況下,a的值可以在a中訪問並在Foo()中修改,並且不存在中間順序點。這是未定義的行爲。

因此,規則「的返回和下一個完整表達之前表達後序列點」是從「a 返回後立即序列點」不同;第一個在這個例子中有未定義的行爲,第二個沒有。

+1

謝謝,6.8/4中的內容正是我一直在尋找的內容。顯然這在C11中得到了澄清,因爲C99沒有§4。儘管我沒有關注未定義行爲的例子,因爲在所有函數參數被評估之後,但在函數被調用之前,還有一個序列點。因此,每個帶有return語句的函數在開始和結束時都由序列點「保護」。所以我相信你的例子僅僅是_unspecified_行爲,因爲我們不知道Foo()或者'a'是否被首先評估。 – Lundin 2013-03-26 14:42:09

+0

@Lundin:關於參數評估和函數調用之間的順序點的好處。這意味着這兩條規則有所不同。我已經更新了答案。 – 2013-03-26 15:42:29

4

我不認爲你會找到你要找的。 no text regarding sequence points can be found這是真的,它只是隱含在6.8節p4。

C++標準(ISO/IEC 14882:2003)在第1.9(腳註11)規定的事實,即返回後的序列點是可明確在C標準的任何位置寫入:

11)函數返回的序列點在ISO C中沒有明確規定,並且在全表達式中可以被認爲是冗餘的,但在C++中額外的清晰度非常重要。在C++中,被調用函數可以終止其執行的更多方式,比如拋出異常。

+0

「暗含暗示」? :) – 2013-03-26 13:15:56

+0

@larsmans是啊......這有點多餘,不是嗎?感謝您的修復。 – Mike 2013-03-26 13:17:26

+0

@Mike謝謝。按照6.8§4的規定,這似乎已在C11中得到糾正。 C99沒有那一段。 – Lundin 2013-03-26 14:42:57