2012-12-13 50 views
1

可能重複:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)左值問題

#include<stdio.h> 

int main() 
{ 
    char a[]="Hello"; 
    char *p=a; 
    while(*p) 
    ++*p++;  //Statement 2 
    printf("%s",a); 
    int x=10; 
    ++x++; //Statement 1 
    return 0; 
} 

當我編譯此代碼我在聲明1,這我可以理解得到的左值所需錯誤。即使我打算做同樣的事情,該聲明2如何不會產生錯誤?有人可以放光嗎?

+0

p在序列點之間被修改兩次,所以這是未定義的行爲。 – Lundin

+3

@Lundin不,它不是。 '++ * p ++'是'++(*(p ++))','p'只修改一次,沒有UB。 –

+0

好吧,有一個問題:爲什麼你想寫這樣的代碼,沒有括號?使用正確的括號和行爲將是可預測的+可讀。 – anishsane

回答

0

從ISO C99標準報價:

6.5.2.4 Postfix increment and decrement operators 

Constraints
1
The operand of the postfix increment or decrement operator shall have qualified or unqualified real or pointer type and shall be a modifiable lvalue.

對於這種情況:

++*p++;  //Statement 2 

後綴++具有更高的優先級和前綴++*具有相同的優先級和right to left關聯。這意味着它的第一步是增加指針而不是值。 所以它會給你的下一個地址type。然後value (which is actually *p)遞增。所以,在這種情況下沒有constraint violation。 與++(*(p++))相同。

對於低於其他情況下:

int x=10; 
++x++; //Statement 1 

在變量的上述情況下(未指針)++(任後綴或前綴增量或減量)給你rvalue,然後在rvalue施加++--constraint violation++--操作數應該是lvalue。見上面寫的標準報價。因此給錯誤。

+0

Postfix ++的優先級高於一元*和前綴++。你似乎混淆了這一點。無論如何,這些代碼都是未定義的行爲,所以它沒有任何目的試圖弄清楚它會做什麼。 – Lundin

+0

@Lundin:對於未定義的行爲不太確定,但'++'和'*'具有相同的優先級...... – Omkant

+0

@Lundin:第2章'K&R'的C編程'2.12優先級和評估順序'請參閱給定的運算符表。請問'++(*(p ++))'表達式的問題,請您解釋一下嗎? – Omkant

3

無法修改預增量和增量後產生的右值和右值。

因此++x++(語句1)顯然是違反約束條件,編譯器會給出錯誤。

但是對於聲明2卻不是這種情況。雖然p++產生的值不能修改,但可以是取消引用。或者,如果你這樣做++p++這將相當於++x++的情況下,會給出一個錯誤。因爲這裏指針本身已被修改。

所以它相當於:++(*p++)

(請注意,括號僅用於理解,並不是必需的,表達式++*p++已定義明確。)

什麼情況是:

  • 的後增量p++計算結果爲p舊值,在這個例子中&a[0],和p存儲的值增加。
  • *p++給出值p之前指向的增量,在本例中爲a[0]
  • 最終的預增量增量值,所以a[0]變成I(可能是EBCDIC機器上的其他東西)。

當被存儲的pa[0]遞增後的值是不確定的,但是它們都必須已經被存儲在下一序列點(端接;)。

+0

你有一個糟糕的表達方式,「後期增量引用了這個問題」。我知道你的意思是正確的,我不知道如何把它說得很好,但是那讀錯了。 (我喜歡預期改進的配方。) –

+0

@DanielFischer當我寫它的時候,我感到有種感覺。不太確定如何重新說話。它看起來更好嗎? –

+0

我試圖更好地解釋它,如果你不喜歡它,請回滾。 –

0
#include<stdio.h> 

int main() 
{ 
    char a[]="Hello"; 
    char *p=a; 
    while(*p) 
    ++*p++;  //Statement 2 
    printf("%s",a); 
    int x=10; 
    ++x=x++; //Statement 1 
    return 0; 
} 

//由於前後同時遞增,此代碼將獲取相同的錯誤。 ,因爲它不能同時分配和增加,它需要一個值來執行增量。