正如标题所说,我在一些C讲义中找到了这样一句话。
我无法发明任何证明这句话的例子。
在我看来,每次赋值操作都会被评估一次,因为当我们想要对它进行多次评估时,我们会在循环中进行评估。那我错过了什么?
我已经搜索过,但在SO上找不到答案。
答案 0 :(得分:6)
(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