2016-07-27 150 views
-2

ISO/IEC 9899(TC2)§6.5 - 2表達告訴我們:爲什麼printf(「%d%d%d」,++ i,i,i ++)是未定義的行爲?

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

這是我記住,記住,並會告訴任何人問我爲什麼從標題行產生意想不到的輸出。

但今天我剛發現這一行:

§7.19.6 - 1格式的輸入/輸出功能:

格式的輸入/輸出功能應表現爲,如果有一個序列點之後與每個說明符相關的操作。

這讓我假設:

雖然

int i = 0; 
printf ("%d, %d", ++i, i++); 

應該是不確定的,接下來的例子應該是由所提到的條款確定:

int i = 0; 
printf ("%d, %d, %d", ++i, i, i++); 

但輸出是:

2, 2, 0 

我從來沒有見過這樣的更好的例子,表明未定義的行爲。

但是爲什麼? 如果該條款爲真

「[[...]」表現得好像每個說明符相關的操作之後有一個序列點。

然後施加§6.5下的規則 - 2到每個與所述指定符相關聯的actiosn不會讓我們越過該規則如:

(表示相關的序列點SP)

SP ++i SP i SP i++

從前一個和下一個SP之間的給定範圍內的SP1開始,++ii存儲值的唯一修改。

從SP2什麼是前一個和下一個SP之間的範圍是:++ii其中++i仍然是該值的唯一修改。

如果我們現在採取SP3一切是怎麼回事以前的SP(SP2)和下一個SP(調用結束)之間是:

ii++仍然只是一個單一的i在整個修改前一個和下一個SP之間的範圍。

那麼我在這裏解釋錯誤的順序點的工作方式?

+0

如果您認爲它適合,可以隨意倒計時。但請注意,這不僅僅是另一個配合問題。我遇到了一些似乎很奇怪的事情,我對此做了一些體面的研究,並清楚地說明了我的困惑以及爲什麼它與此有關的其他問題有所不同。如果你仍然認爲我錯過了某些東西或者沒有做出足夠的努力,請讓我知道你爲什麼這麼想。 – dhein

回答

1

問題不在於與說明符相關的操作。問題在於計算printf函數的參數,該函數在第一個說明符執行任何操作之前完成。

試想一下,如果代碼是:

void foo (int i1, int i2, int i3) 
{ 
    printf("%d, %d, %d", i1, i2, i2); 
} 

foo (++i, i, i++); 

這將是很清楚的。包裝並沒有改變任何東西。

+0

你能否詳細說明在這些情況下,相關行爲之間的順序點是甚至相關的?或者我應該問一個單獨的問題? – dhein

+0

這應該是顯而易見的東西,如'scanf'。可能有一些格式說明符可能會使'printf'變得不同,但我想不出任何。也許別人可以。 –

+2

具體說明格式說明符'%n',它將到目前爲止打印的字符數寫入給定地址。 –

相關問題