2012-08-26 69 views
2

正如標題所說,我在一些C講義中找到了這樣一個句子。算術賦值運算符 - 左側僅評估一次

我不能發明任何證明這句話的例子。

在我看來,每一次賦值操作都會被評估一次,因爲當我們希望對它進行多次評估時,我們會將其放入一個循環中。那麼我錯過了什麼?

我已經搜索,但在這裏找不到答案。

+0

的例子嗎?我不明白.. –

+0

沒有任何實際解釋問題的任務,與例如相反。 'x + = 6' –

+0

請參見[C++中| =運算符的含義](http://stackoverflow.com/questions/4217762/what-does-the-operator-mean-in-c/4217772#4217772)雖然它是針對C++的,但它的確解釋了對運營商的LHS進行一次評估意味着什麼。除了提及運算符重載(僅限於C++),註釋適用於C和'+ ='(和'| ='和其他賦值運算符)。 –

回答

6

Ç說:

(C99,6.5.16.2p3)僅在該左值形式E1 OP = E2從簡單賦值表達式E1 = E1 OP(E2)的不同的「A化合物分配E1只評估一次。「

下面是爲什麼它的問題的一些例子:

實施例1:

a[i++] += 1; 

相同:

a[i] = a[i] + 1; i++; 

由於+=左操作數是評估一次。

如果不是計算一次這將是一樣的:

a[i++] = a[i++] + 1; 

這當然是不同的(和未定義的行爲BTW)。

實施例2:

*foo() += 1; 

foo假設這裏返回一個指向標量類型的對象,併產生副作用(例如它打印在終端上的字符串)。使用複合賦值運算符時,它只會打印一次而不是兩次。

實施例3:

REG |= 0x01; 

REG假設這裏是一個IO寄存器(像#define REG (*(volatile uint8_t *) 0x42))和每讀取該特定IO寄存器觸發硬件事件。該寄存器只能用複合賦值操作符讀取一次,而不能兩次。

編輯:以下@R.評論我刪除線的例子3.我想大多數編譯器不會在這個表達式執行讀:REG = 31或兩個與該表達式如下:REG = REG | 0x01

+0

示例3不正確。無論您是分別使用'| ='或'|'和'=',寄存器都將被精確讀取一次,並且只寫入一次。這是因爲左值引用的對象不是作爲評估'='運算符的一部分讀取的。也許你想到的是''=''可能會在'|'和'='單獨執行時執行單指令讀 - 修改 - 寫週期,但我認爲這個假設是錯誤的; volatile並不要求,並且可能不會(在嚴格閱讀對volatile的要求下)甚至允許它。 –

+0

@R。例3我可能太快了,因爲它不符合現實世界的例子。實際上,大多數編譯器可能不會像'REG = 31'這樣的簡單賦值來進行讀操作(例如http://gcc.gnu中的'vobj1')。org/wiki/VolatileAccessComparison)。但我認爲編譯器可以執行它。我無法看到C語言標準的觀點與此語句有所不同:'REG;'該值也未被使用,但大多數編譯器執行讀取操作。 – ouah

+0

@R。順便謝謝你的評論,我編輯了我的答案。 – ouah

1

你的問題很不明確,措辭也不太好,但我懷疑你的筆記提到的是,組合的算術+賦值運算符允許你做某些事情而不用寫(並因此評估)左值的表達式比一次。例如,

*p++ += *q++; /* p is incremented once, as desired */ 
*p++ = *p++ + *q++; /* undefined behavior */ 

這尤其重要,當你在宏來使用這些,例如:

#define ACCUM(d,s) (d)+=(s) /* good */ 
#define ACCUM(d,s) (d)=(d)+(s) /* dangerous */ 
0

不要有什麼編譯方便,但這裏是一個有趣的花絮:

var1 += var++將VAR1的值更改爲var1 + var

然而

var1 += ++var將VAR1的值更改爲var1 + (var + 1)

+0

我認爲這是問題中的理解(或不是問題);問題是什麼意味着這個任務的LHS被評估一次 - 爲什麼(或什麼時候)這個關鍵? –

+1

哦,我的錯誤我想我完全錯過了這個問題的觀點。 –

0

有一些化合物分配操作在下例如+ =, - =,* =,/ =,%=

例如, i + = 1它將i的值增加1,如i ++。

+0

我認爲這是在問題中理解;問題是什麼意味着這個任務的LHS被評估一次 - 爲什麼(或什麼時候)這個關鍵? –

+0

我已經熟悉你寫的東西,而不是我在這裏問的情況。無論如何感謝活動;) –

2

通常+=操作員通過以下方式介紹:

x += y; 
x = x+y; // does the same 

但是,該說明試圖告訴你,這其實不準確,爲=左側,+=可能是任何表達。正如其他人所說,這可能導致未定義的行爲,但這不是問題的核心。

例如:

char* f() { 
    static char value = 'a'; 
    printf("%c\n",value); 
    return &value; 
} 

void g() { 
    *f() = 'b'; // assigns 'b' which was 'a' 
    *f() += 2; // changes 'b' to 'd' 
    *f() = 'b'; 
    *f() = *f() + 2; // changes 'b' to 'd' 
} 

的區別在於f在最後一行,同時它在第二執行一次執行兩次。

+0

+1不錯的說明示例。 –

0

有複合賦值運算符的數目。例如。 +=,-=,*=,/=,%=

a+=bgive a=a+b 瞭解更多詳情請點擊this