2012-06-18 31 views
7

我的印象是後增量(OR預增量)只能在右側(=)的右側完成。但我可以編譯下面的一段代碼。 你能幫我理解這個特定的代碼,特別是在下面的行。 來源:http://www.ibm.com/developerworks/library/pa-dalign/後增加在左側

*data8++ = -*data8; 


void Munge8(void *data, uint32_t size) { 
    uint8_t *data8 = (uint8_t*) data; 
    uint8_t *data8End = data8 + size; 

    while(data8 != data8End) { 
     *data8++ = -*data8; 
    } 
} 
+0

分配' - * data8'到'* data8'然後增加'data8' - 有效地抵消了'size'在'data' – Erik

回答

3

你的印象是錯誤的,我猜。你絕對可以做這樣的事情:

*a++ = *b++; 

事實上,這通常是如何實現strcpy。你甚至可以有後或預增量沒有=可言:

a++; 
+0

等待字節,所以我同意與您的原始帖子。這不是什麼不確定的行爲? –

+0

strcpy沒有像那樣實現。您首先以大塊數據的位模式查找字符串的結尾,然後以較大的塊(通常爲64位)複製數據。 – 2012-06-18 18:31:40

+0

@sharth:雖然它沒有定義?我不是一個標準的癮君子,但是必須先評估RHS,然後再評估LHS。因此應該沒有問題。 – 2012-06-18 18:33:07

1

有沒有理由後遞增不能賦值運算符的左側進行。後增加運算符只是返回對象在其先前狀態下的臨時副本,並且該臨時對象(在本例中爲指針)可以對其執行操作。

現在,在的情況下:

*data8++ = -*data8; 
因爲運營商訂購的

,該data8指針將首先進行遞增,返回先前的指針值的副本。之前的指針值將被取消引用,並在賦值運算符的右側分配表達式的結果。

編輯:正如其他人所指出的那樣,你是通過讀不止一次在寫入沒有序列點存儲位置更多修改的data8內容,所以這是不確定的行爲。

+0

這是怎麼定義的?這就像聲稱'x = -x'是未定義的。 –

+0

您正在修改'data8'的內容(即指針值本身),然後在沒有序列點的情況下將它讀回兩個不同的位置。正如其他人所指出的那樣,如果首先評估LHS或RHS,您將得到兩個不同的結果...因此「未定義的行爲」,因爲C標準沒有定義首先必須評估哪一方......例如, LHS和RHS的評估可以交錯使用!在你的例子中,有一個明確的評估順序,因爲LHS沒有讀取'x'的值,它只是寫給它。所以只有一個讀/寫。 – Jason

+0

是的。我會聲稱缺乏睡眠作爲藉口。 –

2

++應用於指針,而不是data8指向的值。

*data8++ = -*data8;

等同於:

*data8 = -*data8; 
data8++; 

編輯:
閱讀C99 standard 6.5Annex C後,很明顯=不是一個序列點。標準僅提到&&||,,?

因爲,data8上的=兩面沒有順序點和標準不強制RHS是否應首先評估或LHS應先評估修改,我相信這是未定義行爲。

Any good reason why assignment operator isn't a sequence point?

這上面的帖子討論=是不是一個序列點,這裏是非常相關的。

+0

'data8'在賦值操作符的兩側都沒有被修改,而是在LHS中被修改,但它被讀取了兩次,沒有序列點確定讀取是如何針對寫入進行排序的。 – Jason

+0

@Jason你是對的。 '='不是順序點是這裏的關鍵。 –

7

所以,我很確定這是未定義的行爲。沒有比在最後一個分號其他沒有順序點:

*data8++ = -*data8; 

如果DATA8等於爲0x20,這是等於:

*(0x20) = -*(0x20); 

*(0x20) = -*(0x24); 

因爲沒有做出這一決定的方式,(因爲您在讀取兩次的同時編輯了一個變量,沒有交錯序列點),這是未定義的行爲


雖然我們可以談論下面的代碼片段是做什麼的。這可能是上述代碼的意圖。

while(data8 != data8End) { 
    *data8 = -*data8; 
    data8++; 
} 

你在這裏做的是希望更直接的。你正在把你的輸入數組,看着它,所以它是一系列的8位數字。然後,就地,你否定每一個。

+0

我認爲你在這裏混淆了「變量」。由地址指針存儲的指針值和值是兩個不同的東西。在這種情況下,沒有人在讀兩次的同時編輯了一個變量。地址指針處的「data8」值在RHS上讀取一次。它被寫回一次。指針在LHS上更改一次。 – 2012-06-18 18:45:16

+0

或者我可以。 Hehe – 2012-06-18 18:48:25

+2

@Vlad,'='不是序列點。 –

0

我認爲

* DATA8 ++ = - * DATA8;

相當於

* DATA8 = - *(DATA8 + 1);

DATA8 = DATA8 +1