有什么区别 i = i + j
; 和i += j
; 在 C? 它们是等价的吗?有没有副作用i
?
我试图使用 GCC 编译器检查 C 中的分配机制。
他们几乎是一样的。唯一的区别是i
在这种情况下只评估一次,+=
而在另一种情况下只评估两次。
几乎没有区别,但如果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;
i = i + j
和,这两个语句i += j
在功能上是相同的,在第一种情况下,您使用的是一般赋值操作,而第二种情况使用combinatorial assignment operator
. +=
是additive assignment operator
(加法后赋值)。组合赋值运算符的使用会生成smaller source code
isless susceptible to maintenance errors
并且也可能会在smaller object code
其中运行得更快。Compilation is also likely to be a little faster
.
在这两种情况下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'
or a
is volatile
(不管b
or c
),那么它们是不等价的,因为第二个将评估为:
c = b + j
对于输入"Y\n"
,b = b + j
对于输入"\n\n"
,c = c + j
用于输入"YN"
。这些点当然大部分是无关紧要的——如果你编写这样的代码并且它做了你没想到的事情,同情可能会供不应求!