2014-10-20 109 views
5

我很困惑,爲什麼我的編譯器在以下條件拋出一個錯誤:Ç - 表達式必須爲可修改的左值

void funcExample (void * p_Buf, uint16_t len) 
{ 
    uint16_t i; 

    for (i = 0; i < len; i++) { 
     otherFunc (((uint8_t *)p_Buf)++); //error = expression must be a modifiable lvalue 
    } 
} 

,但傳遞給otherFunc之前,如果我投,因爲沒有任何問題遞增的罰款一個非空指針:

void funcExample (void * p_Buf, uint16_t len) 
{ 
    uint16_t i; 
    uint8_t * p_Buf_8bit; 

    p_Buf_8bit = (uint8_t *) p_Buf; 

    for (i = 0; i < len; i++) { 
     otherFunc (p_Buf_8bit++); 
    } 
} 

不能在虛擬指針增加一次投射?我在這裏錯過了什麼?

+0

不一樣,但*非常* [**類似的問題在這裏**](http://stackoverflow.com/questions/24002044 /爲什麼燦I-不-DO-算術上-A-鑄造的-A-空指針)。 – WhozCraig 2014-10-20 17:08:36

回答

5

轉換操作符:使用此而不是

6.5.4。 p5在帶括號的類型名稱前面添加一個表達式,將 表達式的值轉換爲指定的類型。 這種結構被稱爲演員。 104)指定 的轉換不會影響表達式的類型或值。

104)演員陣容不產生左值。因此,流延到一個合格的類型具有作爲鑄造的類型

但一元運算符++的 不合格版本相同的效果,需要如所述左值:

6.5.3.1 。 p1前綴增量或減量運算符的操作數應該是原子的,合格的, 或非限定的實數或指針類型,,並且應該是可修改的左值。

因此你可以這樣做:

p_Buf = (uint8_t*)p_Buf + 1 ; 

哪裏p_Buf是左值和(uint8_t*)p_Buf是右值。


讓我注意到,在你的第二個例子中,你不投(如你所說),但你聲明uint8_t的指針。然後當你使用++時,你不會執行任何強制轉換(因爲它具有正確的類型)並且操作是有效的。

+0

您正將'void'指針轉換爲'uint8_t'而不是指向它的指針。 – Seprum 2014-10-20 17:06:03

+0

@Seprum不,我不是。你可能看過一箇舊的編輯。刷新頁面。 – 2501 2014-10-20 17:06:20

+0

已經編輯。 – Seprum 2014-10-20 17:07:29

0

轉換操作的結果是一個右值,而不是左值。 ((uint8_t *)p_Buf)++根本就不是合法的C代碼。

1

遞增void指針C是個壞主意。大多數編譯器甚至不讓它被編譯。在C

p_Buf = (uint8_t*)p_Buf + 1; 
1

發佈的答案@ 2501絕對正確,但並不能解釋爲什麼該標準要求左值用於後增量。基本原因是你需要一個左值(變量或內存位置)進行後增量以執行其增量。

當您將p_Buf轉換爲uint8_t*類型時,您在C中創建了一個右值。簡單地說,rvalues表示可以傳遞給函數,分配給變量等的瞬態值。後增量返回原始值,然後更新存儲值的變量或內存位置,並將其遞增。因爲它們只存在於表達式的持續時間內,所以rvalues不能被更新,並且後增加不能對它們進行操作。因此,與

otherFunc (((uint8_t *)p_Buf)++); //error = expression must be a modifiable lvalue 

的問題是,((uint8_t *)pBuf)只是一個右值表達與沒有實際的存儲位置。實際上,演員表示您只使用p_Buf的值,不再直接使用變量p_Buf

在另一方面,當鑄分配給一個變量:

p_Buf_8bit = (uint8_t *) p_Buf; 

那麼變量p_Buf_8bit左值,它代表一個變量或內存位置。這可以後遞增,使這是一個完美的格式良好的陳述在C:

otherFunc (p_Buf_8bit++); 
+0

感謝您的額外解釋 - >這真的有幫助。問題是演員的臨時/短暫性質(右值vs左值)。謝謝。 – jaypee 2014-10-20 20:17:54

相關問題