正如标题所说,我在一些C讲义中找到了这样一个句子。算术赋值运算符 - 左侧仅评估一次
我不能发明任何证明这句话的例子。
在我看来,每一次赋值操作都会被评估一次,因为当我们希望对它进行多次评估时,我们会将其放入一个循环中。那么我错过了什么?
我已经搜索,但在这里找不到答案。
正如标题所说,我在一些C讲义中找到了这样一个句子。算术赋值运算符 - 左侧仅评估一次
我不能发明任何证明这句话的例子。
在我看来,每一次赋值操作都会被评估一次,因为当我们希望对它进行多次评估时,我们会将其放入一个循环中。那么我错过了什么?
我已经搜索,但在这里找不到答案。
Ç说:
(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
。
示例3不正确。无论您是分别使用'| ='或'|'和'=',寄存器都将被精确读取一次,并且只写入一次。这是因为左值引用的对象不是作为评估'='运算符的一部分读取的。也许你想到的是''=''可能会在'|'和'='单独执行时执行单指令读 - 修改 - 写周期,但我认为这个假设是错误的; volatile并不要求,并且可能不会(在严格阅读对volatile的要求下)甚至允许它。 –
@R。例3我可能太快了,因为它不符合现实世界的例子。实际上,大多数编译器可能不会像'REG = 31'这样的简单赋值来进行读操作(例如http://gcc.gnu中的'vobj1')。org/wiki/VolatileAccessComparison)。但我认为编译器可以执行它。我无法看到C语言标准的观点与此语句有所不同:'REG;'该值也未被使用,但大多数编译器执行读取操作。 – ouah
@R。顺便谢谢你的评论,我编辑了我的答案。 – ouah
你的问题很不明确,措辞也不太好,但我怀疑你的笔记提到的是,组合的算术+赋值运算符允许你做某些事情而不用写(并因此评估)左值的表达式比一次。例如,
*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 */
不要有什么编译方便,但这里是一个有趣的花絮:
var1 += var++
将VAR1的值更改为var1 + var
var1 += ++var
将VAR1的值更改为var1 + (var + 1)
我认为这是问题中的理解(或不是问题);问题是什么意味着这个任务的LHS被评估一次 - 为什么(或什么时候)这个关键? –
哦,我的错误我想我完全错过了这个问题的观点。 –
有一些化合物分配操作在下例如+ =, - =,* =,/ =,%=
例如, i + = 1它将i的值增加1,如i ++。
我认为这是在问题中理解;问题是什么意味着这个任务的LHS被评估一次 - 为什么(或什么时候)这个关键? –
我已经熟悉你写的东西,而不是我在这里问的情况。无论如何感谢活动;) –
通常+=
操作员通过以下方式介绍:
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
在最后一行,同时它在第二执行一次执行两次。
+1不错的说明示例。 –
有复合赋值运算符的数目。例如。 +=,-=,*=,/=,%=
为a+=b
将give a=a+b
了解更多详情请点击this
的例子吗?我不明白.. –
没有任何实际解释问题的任务,与例如相反。 'x + = 6' –
请参见[C++中| =运算符的含义](http://stackoverflow.com/questions/4217762/what-does-the-operator-mean-in-c/4217772#4217772)虽然它是针对C++的,但它的确解释了对运营商的LHS进行一次评估意味着什么。除了提及运算符重载(仅限于C++),注释适用于C和'+ ='(和'| ='和其他赋值运算符)。 –