算术赋值运算符 - 左侧仅计算一次 [英] Arithmetic assignment operator - left side evaluated only once
问题描述
正如标题所说,我在一些 C 讲义中发现了这样一句话.
As the title says I found such a sentence in some C lecture notes.
我想不出任何例子来证明这句话.
I can't invent any example proving that sentence.
在我看来,每个赋值操作都被评估一次,因为当我们希望它被评估多次时,我们会放入一个循环中.那我错过了什么?
In my opinion every of assignment operations is evaluated once, because when we want it to be evaluated more than once we put in in a loop. What am I missing then?
我已经搜索过,但在 SO 上找不到答案.
I've searched but couldn't find an answer here on SO.
推荐答案
C 说:
(C99, 6.5.16.2p3) E1 op= E2 形式的复合赋值与简单赋值表达式 E1 = E1 op (E2) 的不同之处仅在于左值 E1 只计算一次."
(C99, 6.5.16.2p3) "A compound assignment of the form E1 op= E2 differs from the simple assignment expression E1 = E1 op (E2) only in that the lvalue E1 is evaluated only once."
以下是其重要性的一些示例:
Below are some examples of why it matters:
示例 1:
a[i++] += 1;
等同于:
a[i] = a[i] + 1; i++;
因为 +=
的左操作数被评估一次.
because the left operand of +=
is evaluated once.
如果它没有被评估一次,它将与:
If it was not evaluated once it would be the same as:
a[i++] = a[i++] + 1;
这当然是不同的(顺便说一句,还有未定义的行为).
which is of course different (and undefined behavior BTW).
示例 2:
*foo() += 1;
假设 foo
在这里返回一个指向标量类型对象的指针并产生副作用(例如它在终端上打印一个字符串).使用复合赋值运算符,它只会打印一次字符串,而不是两次.
assuming foo
here returns a pointer to an object of a scalar type and produces side effects (for example it prints a string on the terminal). With the compound assignment operator it will print the string only once and not two times.
示例 3:
REG |= 0x01;
假设 REG
这里是一个 IO 寄存器(类似于 #define REG (*(volatile uint8_t *) 0x42)
)并且每次读取这个特定的 IO 寄存器都会触发硬件事件.使用复合赋值运算符只会读取寄存器一次,而不是两次.
assuming REG
here is an IO register (something like #define REG (*(volatile uint8_t *) 0x42)
) and that every read to this specific IO register triggers a hardware event. The register will be read only once with the compound assignment operator and not two times.
EDIT:按照 @R. 评论我击中了示例 3.我认为最编译器不会在此表达式中执行读取:REG = 31
或使用此表达式执行两次读取:REG = REG |0x01
.
EDIT: following @R. comment I striked the example 3. I think most compilers do not perform a read in this expression: REG = 31
or two reads with this expression: REG = REG | 0x01
.
这篇关于算术赋值运算符 - 左侧仅计算一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!