2013-11-01 47 views
0
#include<stdio.h> 
int main() 
{ 
    int i=2; 
    printf("%d %d \n",++i,++i); 
} 

上面的代碼給出了輸出4 4。任何人都可以幫助解釋輸出嗎?C中的printf()的意外工作

+1

這是未定義的行爲。請參閱此處的示例 http://stackoverflow.com/questions/19694756/how-pre-and-postfix-are-evaluated-in-printf – jaap

回答

1

它與序列點有關,它可能導致未定義的行爲。維基百科

直:一個函數在一個函數調用進入

之前。 參數評估的順序沒有指定,但是這個順序點 意味着它們的所有副作用在輸入函數 之前完成。

此處瞭解詳情:http://en.wikipedia.org/wiki/Sequence_point

2

++ i是前綴增量。 Printf應該先打印它們的參數,然後再打印它們(儘管順序無法保證,嚴格來說,未定義 - 請參閱未定義行爲上的Wiki條目:http://en.wikipedia.org/wiki/Undefined_behavior)。

前綴增量被稱爲「增量和提取」,即它首先遞增該值,然後將其提供給調用者。

在你的情況下,i第一次增加了兩次,只有之後輸出格式化併發送到控制檯。

+0

此答案是如何得到投票的?在func(a,a ++)中,不是逗號運算符,它僅僅是參數a和++之間的分隔符。在這種情況下,行爲是不確定的,如果a被認爲是原始類型)' – Sadique

+0

@Acme我投了票,它根本沒有提到逗號運算符?但它確實提到這只是一個函數調用,並且調用需要在進行實際調用之前評估其所有參數,這似乎是混淆OP的一點。 – unwind

+0

@unwind - 你在說什麼和在答案中有細微的差別。答案是談論評估的順序是未指定的,這是正確的,但它沒有提到它是UB。這'在你的情況下,我第一次增加了兩次,然後才輸出格式化併發送到控制檯.'是不正確的。這個'printf(「%d%d \ n」,++ i,++ i);'是明確的UB。先評估一下這個''%d%d \ n「',這個'++ i'還是這個'++ i' - 考慮一下。 – Sadique

0

這兩個答案都犯了同樣的錯誤。它清晰的UB,而不僅僅是不明確的行爲。

你所經歷的是Undefined behavior。請閱讀有關順序點。逗號是函數調用中的分隔符,不是操作符。

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

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

標準指出

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

什麼將首先這"%d %d \n"評估,這++i或本++i(第二個) - 想想吧。在函數調用輸入函數之前

:這將是不確定的行爲:

void f(int x) 
{ 
    printf("%d ",x); 
} 
int main() 
{ 
    int i=0; 
    f(i++) ; 
} 

從維基。 參數評估的順序沒有指定,但是這個順序點 意味着它們的所有副作用在輸入函數 之前完成。在表達式f(i ++)+ g(j ++)+ h(k ++)中,f被稱爲 ,其參數爲i的原始值,但i在進入f的主體之前增加 。類似地,j和k分別在 分別輸入g和h之前更新。但是,並沒有規定執行哪個命令f(),g(),h(),也不知道i,j,k的遞增順序。 f主體中的變量j和k可能已經或可能沒有 已經增加。請注意,函數調用f(a,b,c)不是使用逗號運算符的 ,未指定a,b和c的評估順序。