2013-07-17 94 views
2

C99標準是否允許將變量分配給自己?舉例來說,有以下幾種有效:C99標準是否允許爲自己分配一個變量?

int a = 42; 

/* Case 1 */ 
a = a; 

/* Case 2 */ 
int *b = &a; 
a = *b; 

雖然我懷疑病例1是有效的,我很猶豫,說同樣的情況2

在轉讓的情況下,是右側完全評估之前將值分配給左側的變量 - 或者是取消引用指向所分配的變量的指針時引入的競爭條件?

+1

'a = a;'是高級語言中的死指令,我非常肯定優化階段會將其刪除 –

+1

@GrijeshChauhan並不總是如果a在內存中並且不需要優化。看我下面的例子。 – hivert

+2

只要變量已經正確初始化,你應該沒問題。如果變量未初始化,則複製未初始化的值不會使其更好地初始化。如果變量是volatile,它可能不是空操作(編譯器必須讀取該值並寫入再次讀回的值)。當變量不符合volatile時,它應該是no-op。 –

回答

4

兩種情況都是完全有效的,因爲a的值僅用於確定要存儲的值,而不是確定要存儲該值的對象。

在你必須區分三種不同的操作

  • 確定到的值是要被存儲
  • 評價RHS
  • 存儲在所確定的對象所確定的值的對象的分配本質

這三個操作中的前兩個操作可以以任何順序完成,即使並行。第三個顯然是另外兩個的結果,所以它會出現。

3

這是完全有效的,你只使用以前的值來確定要存儲的值。這是包括在draft C99 standard6.5.2它說:

之前和下一序列點之間的對象應具有由 expression.Furthermore的評價中,前一個值改性至多一次其 儲值只讀爲 確定要存儲的值。

之一的有效代碼的示例如下:

i = i + 1; 

C和C++部here涵蓋可以發生的序列點不同的地方。

2

假設編譯器不會通過簡單地刪除第一條指令來優化第一條指令,這裏甚至存在競爭條件。在大多數體系結構中,如果a被存儲在內存中,a = a將被編譯爲兩條移動指令(mem => reg,reg => mem),因此不是原子性的。

下面是一個例子:

int a = 1; 
int main() 
{ a = a; } 

在Intel x86_64的用gcc結果4.7.1

4004f0:  8b 05 22 0b 20 00  mov 0x200b22(%rip),%eax  # 601018 <a> 
4004f6:  89 05 1c 0b 20 00  mov %eax,0x200b1c(%rip)  # 601018 <a> 
+0

但你是*假設*,你試過嗎?爲什麼沒有任何編譯器不能刪除它?它很容易做到檢測。這是你真實的例子嗎?哪個編譯器? –

+0

雖然@GrijeshChauhan可能是正確的,現代編譯器很可能不會這樣做,但我對C99標準是否允許這種行爲感興趣 - 畢竟,編譯器不必*實用*成爲*符合標準*。 –

+0

hmm hivert推出了它會是如果編譯器不優化它,所以它的好答案。 –

2

C99 6.5.16。1簡單賦值

3如果被存儲在一個對象的值是從以任何方式 第一個對象的存儲重疊的另一目的讀取,則重疊應爲精確和兩個對象應 有資格或兼容類型的非限定版本;否則,行爲是未定義的 。

我認爲示例代碼限定了「重疊」條件。由於它們具有兼容類型的限定版本,因此結果是有效的。

另外6.5.16賦值運算符

4的操作數的評價的順序是不確定的。如果嘗試修改賦值運算符的結果或在下一個序列點之後訪問它,則 行爲未定義。

仍然沒有「嘗試修改結果」,所以結果是有效的。

+0

關於段落4('如果試圖修改賦值操作符的結果或在下一個序列點之後訪問它,行爲是未定義的。因爲'a'在評估之前被修改:'a = ++ a'?什麼是*序列點*? –

+1

@VilhelmGray這是一個關於序列點的很好的參考:http://en.wikipedia.org/wiki/Sequence_point它有一個關於C和C++的部分,什麼是序列點。 –

+0

@VilhelmGray是的,這是正確的,幻燈片197有這個例子:http://www.slideshare.net/olvemaudal/deep-c和這個頁面有更多這樣的例子:https://www.securecoding.cert.org /confluence/display/seccode/EXP30-C.+Do+not+depend+on+order+of+evaluation+between+sequence+points –

0

我看不到C編譯器而不是允許a = a。由於沒有程序員知道它的宏,這種分配可能偶然發生。它甚至可能不會生成任何代碼,這是一個優化問題。

#define FOO (a) 
... 
a = FOO; 

示例代碼很容易編譯,我對C標準的審查顯示不禁止。

至於比賽條件@於皓回答得好:沒有比賽條件。

相關問題