用c语言复合赋值,v + = e与v = v + e有何不同?

时间:2019-04-23 13:50:07

标签: c operator-precedence

在本书的第4章“复合赋值:第二节C编程:现代方法”部分中,说:

  

请注意,我一直在注意不要说v += ev = v + e“等效”。一个问题是运算符优先级:i * = j + ki = i * j + k不同。

我编写了一个程序来比较i * = j + ki = 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 + ki = i * j + k不同?

感谢所有答复。我误解了复合赋值运算符。而且我写了一个误导性的测试。 我想说的是,你们很高兴讨论技术问题并一起学习。在中国找不到如此出色的网站和像您这样的人。

2 个答案:

答案 0 :(得分:6)

如果您感到困惑,请看看operator precedence chart

就您而言,

i *= j + 10;

相同
i *= (j + 10);

相同
i = i * (j + 10);

但是

k = k * j + 10;

相同
k = (k * j) + 10;

根据输出:尝试不同的值。

例如,如果我选择ik作为2,则输出将为

  

i = 24 k = 14

答案 1 :(得分:2)

简短回答:

很明显,它们指的是运算符优先级。那就是:

  • 表达式public class MyScrollView extends ScrollView { static final int CONST_THUMB = 100; // thumb height float divider = 1; public MyScrollView(Context context) { super(context); } @Override public int computeVerticalScrollExtent() { int length = computeVerticalScrollRange() - super.computeVerticalScrollExtent(); if(length > 0) divider = (float )(computeVerticalScrollRange() - CONST_THUMB)/(float )length; else return super.computeVerticalScrollExtent(); return CONST_THUMB; } @Override public int computeVerticalScrollOffset() { return (int )((float )super.computeVerticalScrollOffset() * divider); } } 等效于i = i * j + k
  • 但是i = (i * j) + k等同于i *= j + k

现在当然,如果使用i = i * (j + k);之类的错误输入,那么运气不好,这两个表达式的结果将相同。不是因为C语言,而是因为小学数学。

(如果您是初学者,可以在这里停止阅读)


关于赋值运算符等效性的高级答案:

复合分配(i=1, j=1, k=1)与简单分配*=并不完全等效。标准C17 6.5.16.2说:

  

E1 op = E2 形式的化合物赋值等效于简单赋值表达式 E1 = E1 操作(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)。这是因为在后一种情况下会产生额外的副作用。


1)左FOO和右FOO之间的评估顺序未指定,因此可以给出不同的结果-这是未指定的行为。