3

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

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

在我看来,每个赋值操作都会被评估一次,因为当我们希望它被多次评估时,我们会进入一个循环。那我错过了什么?

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

4

6 回答 6

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;

这当然是不同的(顺便说一句未定义的行为)。

示例 2:

*foo() += 1;

假设foo这里返回一个指向标量类型对象的指针并产生副作用(例如,它在终端上打印一个字符串)。使用复合赋值运算符,它将只打印一次字符串,而不是两次。

示例 3:

REG |= 0x01;

假设REG这里是一个 IO 寄存器(类似于 #define REG (*(volatile uint8_t *) 0x42)),并且每次读取这个特定的 IO 寄存器都会触发一个硬件事件。使用复合赋值运算符将只读取一次寄存器,而不是两次。

编辑:跟随@R。评论我打了这个例子3。我认为大多数编译器不会在这个表达式中执行一次读取:REG = 31或使用这个表达式进行两次读取:REG = REG | 0x01

于 2012-08-26T20:43:37.677 回答
2

通常+=操作符的引入方式如下:

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

=但是,注释试图告诉您这实际上是不准确的,因为and的左侧+=可能是任何表达式。正如其他人所说,这可能导致不确定的行为,但这不是问题的核心。

例如:

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在最后一行执行两次,而在第二行执行一次。

于 2012-08-26T21:03:02.500 回答
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 */
于 2012-08-26T20:45:53.753 回答
0

没有任何东西可以方便地编译,但这里有一个有趣的花絮:

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

然而

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

于 2012-08-26T20:59:12.457 回答
0

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

例如i += 1它像i++一样将 i 的值增加1 。

于 2012-08-26T20:59:22.527 回答
0

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

a+=b更多give a=a+b 详情请点击这里

于 2013-02-12T19:31:58.157 回答