算术赋值运算符 - 左侧仅计算一次

时间:2012-08-26 20:41:13

标签: c variable-assignment

正如标题所说,我在一些C讲义中找到了这样一句话。

我无法发明任何证明这句话的例子。

在我看来,每次赋值操作都会被评估一次,因为当我们想要对它进行多次评估时,我们会在循环中进行评估。那我错过了什么?

我已经搜索过,但在SO上找不到答案。

6 个答案:

答案 0 :(得分:6)

C说:

  

(C99,6.5.16.2p3)“形式E1 op = E2的复合赋值与简单赋值表达式E1 = E1 op(E2)的区别仅在于左值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

答案 1 :(得分: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在最后一行执行两次,而在第二行执行一次。

答案 2 :(得分: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 */

答案 3 :(得分:0)

没有任何方便编译,但这是一个有趣的花絮:

var1 += var++会将var1的值更改为var1 + var

然而

var1 += ++var会将var1的值更改为var1 + (var + 1)

答案 4 :(得分:0)

C中有一些复合赋值操作,例如 + =, - =,* =,/ =,%=

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

答案 5 :(得分:0)

有许多复合赋值运算符。例如。 +=,-=,*=,/=,%=

a+=b give a=a+b 有关详细信息,请单击this