i = i + j
之间有什么区别;和i += j
;在C?
它们是等价的吗? i
有任何副作用吗?
我试图使用GCC编译器检查C中的赋值机制。
答案 0 :(得分:8)
他们几乎一样。唯一的区别是i
仅在+=
案例中评估一次,而在另一案例中评估两次。
答案 1 :(得分:5)
几乎没有区别,但如果i
是一个复杂的表达式,它只计算一次。假设你有:
int ia[] = {1, 2, 3, 4, 5};
int *pi = &(ia[0]); // Yes, I know. I could just have written pi = ia;
*pi++ += 10;
// ia now is {11, 2, 3, 4, 5}.
// pi now points to ia[1].
// Note this would be undefined behavior:
*pi++ = *pi++ + 10;
答案 2 :(得分:4)
i = i + j
等效至i += j
但相同。
在某些情况下(罕见)i += j
与i = i + j
不同,因为i
本身有side effect。
还有一个问题是operator precedence,即
i = i * j + k;
与
不同i *= j + k;
答案 3 :(得分:2)
两个语句i = i + j
和i += j
在功能上是相同的,第一种情况是使用常规赋值操作,而第二种语句使用combinatorial assignment operator
。 +=
为additive assignment operator
(添加后跟作业)。
组合赋值运算符的使用生成smaller source code
less susceptible to maintenance errors
,也可能smaller object code
,它也会运行得更快。 Compilation is also likely to be a little faster
。
答案 4 :(得分:1)
答案 5 :(得分:1)
在这两种情况下i
(要分配的变量或表达式)必须是左值。在大多数情况下,只要i
未声明为volatile
,这将产生两种情况相同的代码。
然而,在某些情况下,左值可能是涉及运算符的表达式,这可能会导致i
的评估两次。可能以这种方式使用的左值表达式的最合理的示例可能是对指针(*p
)的简单解除引用:
*p = *p + j ;
*p += j ;
可以生成不同的代码,但它经过了简单的优化,所以即使没有启用优化,我也没想到。同样p
不能是volatile
,否则表达式在语义上是不同的。
不太合理的情况是使用条件运算符表达式作为左值。例如,以下内容将j
添加到b
或c
,具体取决于a
:
(a ? b : c) += j ;
(a ? b : c) = (a ? b : c) + j ;
这些可能会生成不同的代码 - 编译器可能无法找到该成语并应用优化。如果表达式a
有副作用 - 例如表达式getchar() == '\n'
或a
为volatile
(无论b
还是c
),然后它们不等同,因为第二个会评估为:
c = b + j
输入"Y\n"
,b = b + j
输入"\n\n"
,c = c + j
输入"YN"
。这些要点当然大多是无关紧要的 - 如果你编写这样的代码并且它做了你没想到的事情,那么同情可能是供不应求的!