关于K&R《C程序设计语言》中复合赋值运算符expr1计算次数的疑问
问题解答
关于expr1是否必须是左值
没错,不管是使用复合赋值(op=)还是普通赋值,expr1都必须是可修改的左值。因为赋值操作的本质是把计算结果存储到可寻址的内存位置,只有左值(比如变量、数组元素、解引用的指针等)能满足这个要求。如果expr1是像a + b这样的右值,不管用哪种赋值方式都会编译报错——你没法把值赋给一个临时计算结果。
关于“expr1仅计算一次”的含义
这句话的核心是处理带副作用的表达式。如果expr1包含会改变程序状态的操作(比如自增++、自减--,或者调用有副作用的函数),复合赋值和普通赋值的行为会完全不同:
- 用复合赋值
expr1 op= expr2时,expr1只会被计算一次:先算出expr1对应的内存位置和当前值,完成运算后再把结果存回这个位置,整个过程中expr1里的副作用只触发一次。 - 换成普通赋值
expr1 = (expr1) op (expr2)时,expr1会被计算两次:一次是在右边取它的值参与运算,另一次是在左边确定赋值的目标位置。如果expr1有副作用,这两次计算会分别触发副作用,导致结果和预期不符。
举个实际的例子:
int arr[5] = {0}; int idx = 0; // 使用复合赋值 arr[++idx] += 3; // 这里++idx只执行1次,idx变为1,arr[1] = 0 + 3 = 3
如果换成普通赋值写法:
int arr[5] = {0}; int idx = 0; arr[++idx] = arr[++idx] + 3; // 这里++idx执行了2次,idx变为2,arr[2] = 0 + 3 = 3,arr[1]仍然是0
可以看到,两种写法的结果差异完全来自于expr1(这里是arr[++idx])的计算次数不同。
内容的提问来源于stack exchange,提问作者Azi muth
相关产品推荐
相关产品推荐

