2013-10-24 64 views
1

這是從Deep C一個例子(滑動194)'a ++&f(a)`未定義或未指定?

int a = 41; 
a++ & printf("%d\n", a); 

呈現聲稱的結果是不確定的。爲什麼? a只在序列點之間分配一次。我認爲a++printf之間的執行順序是未指定的,所以這將在所有符合的編譯器上打印41或42,而沒有未定義的行爲。

回答

5

在這一行 - a++ & printf("%d\n", a);只有一個序列點(不包括函數參數中會發生什麼 - 因爲a++1發生在這一行本身) - 修改一個變量並在同一時間內在單個序列中讀取它是UB。如果以前的值是從對象中讀取的,但是也存在修改,則行爲未定義,如i * i++

&&是一個序列點,如果這是您混淆的地方,則不是序列點。

一個序列點是一個時間點,在這個時間點,塵埃已經沉澱,並且迄今爲止看到的所有副作用都保證完成。在C標準中列出的序列的要點是:

在一個完整表達式(全 表達式是一個表達式語句,或任何其他表達這 不是任何更大的表達式內的子表達式的評估的端部); at ||,& &,?:和逗號運算符;和 在一個函數調用(在評估所有參數之後,並且在實際調用之前)。

標準指出

之前和下一序列點之間的對象應具有由表達式的評估修飾的至多一次其 存儲的值。 此外,只有在訪問先前值時才能確定要存儲的值。

+0

謝謝,我不知道我們不能在序列點之間修改和讀取。 (顯然下面的幻燈片解釋說) – Andreas

+0

@Andreas - 我花了很長時間纔將它理解爲UB :) – Sadique

+1

'a ++&printf(「%d \ n」,a)中有兩個順序點;'' 。評估'printf'及其參數之後,但在實際調用之前以及完整表達式末尾處有一個序列點。 –

3

位運算符&沒有引入序列點,所以這確實是未定義的行爲。

+0

我知道。我們仍然只分配一次。 – Andreas

+2

@Andreas - 在一個序列中同時修改一個變量並從中讀取是UB。 – Sadique

+2

「在一個單一的時間點內」使Euclid在他的墳墓中滾動。一個點沒有部分:沒有寬度,長度或寬度。 –