在第4章,本书的复合作业部分:C编程:现代方法,第2版,说:
请注意,我一直小心不要说
v += e
与v = v + e
“相当”。一个问题是运算符优先级:i * = j + k
与i = i * j + k
不同。
我写了一个程序来比较i * = j + k
和i = i * j + k
。但结果是一样的。
#include <stdio.h>
int main() {
int i = 1;
int j = 2;
i *= j + 10;
int k = 1;
k = k * j + 10;
printf("j=%d k=%d\n", i, k);
}
j = 12 k = 12
所以我的问题是:为什么i * = j + k
和i = i * j + k
不一样?
感谢所有的答复。我误解了复合赋值运算符。而且我写了一个误导性的测试。我想说你们很高兴讨论技术问题并一起学习。我在中国找不到这么棒的网站和像你这样的人。
如果你感到困惑,看看operator precedence chart
在你的情况下,
i *= j + 10;
和...一样
i *= (j + 10);
与...相同
i = i * (j + 10);
然而,
k = k * j + 10;
和...一样
k = (k * j) + 10;
根据输出:尝试不同的值。
例如,如果我选择i
和k
作为2
,输出将是
i = 24 k = 14
简短回答:
很明显,它们引用了运算符优先级。那是:
i = i * j + k
相当于i = (i * j) + k
。i *= j + k
相当于i = i * (j + k);
。当然,如果你使用像i=1, j=1, k=1
这样的错误输入,这两个表达式的结果将是相同的,运气不好。不是因为C语言而是因为小学数学。
(如果你是初学者,你可以在这里停止阅读)
有关赋值运算符等价性的高级答案:
复合赋值(*=
)并不完全等同于简单赋值=
。标准C17 6.5.16.2说:
形式E1 op = E2的复合赋值等效于简单赋值表达式E1 = E1 op(E2),除了左值E1仅被计算一次
这意味着如果读取操作数E1包含副作用,则复合赋值与简单赋值不同。考虑这个人为但有效的例子:
int foo (void)
{
static int n=0;
return ++n;
}
int array[3] = {1,2,3};
int* ptr = array;
#define FOO *(ptr + foo())
FOO += 1;
给出了一个数组1 3 3
但FOO = FOO + 1;
可以给出一个数组1 4 3
1)。这是因为在后一种情况下会产生额外的副作用。
1)左FOO和右FOO之间的评估顺序未指定,因此它可以给出不同的结果 - 它是未指定的行为。