3

有什么区别 i = i + j; 和i += j; 在 C? 它们是等价的吗?有没有副作用i

我试图使用 GCC 编译器检查 C 中的分配机制。

4

6 回答 6

8

他们几乎是一样的。唯一的区别是i在这种情况下只评估一次,+=而在另一种情况下只评估两次。

于 2013-07-16T18:06:18.833 回答
5

i = i + j相当于但不一样_ 在某些情况下(罕见)不同于因为它本身有副作用。 还有一个问题是运算符优先级,即i += j
i += ji = i + ji

i = i * j + k;

不一样

i *= j + k;  
于 2013-07-16T18:06:44.787 回答
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;
于 2013-07-16T18:10:24.777 回答
2

i = i + j和,这两个语句i += j在功能上是相同的,在第一种情况下,您使用的是一般赋值操作,而第二种情况使用combinatorial assignment operator. +=additive assignment operator(加法后赋值)。组合赋值运算符的使用会生成smaller source codeisless susceptible to maintenance errors并且也可能会在smaller object code其中运行得更快。Compilation is also likely to be a little faster.

于 2013-07-16T18:57:30.760 回答
1

语法糖宝宝。

任何差异都将归结为编译器实现。

http://en.wikipedia.org/wiki/Syntactic_sugar

于 2013-07-16T18:09:20.743 回答
1

在这两种情况下i(被赋值的变量或表达式)都必须是左值。在大多数简单的情况下,只要i没有声明,这将产生在两种情况下都相同的代码volatile

但是,在少数情况下,左值可以是涉及运算符的表达式,这可能会导致计算i两次。可能以这种方式使用的左值表达式的最合理示例可能是指针 ( *p) 的简单解引用:

*p = *p + j ;
*p += j ;

可能会生成不同的代码,但它经过了微不足道的优化,所以我预计即使没有启用优化也不会。同样p不能是volatile,否则表达式在语义上是不同的。

一个不太合理的场景是使用条件运算符表达式作为左值。例如,以下添加jbc取决于a

(a ? b : c) += j ; 
(a ? b : c) = (a ? b : c) + j ;

这些可能会生成不同的代码——编译器可能不会合理地发现该习惯用法并应用优化。如果表达式a有副作用 - 例如是表达式getchar() == '\n'or ais volatile(不管bor c),那么它们是不等价的,因为第二个将评估为:

  • c = b + j对于输入"Y\n"
  • b = b + j对于输入"\n\n"
  • c = c + j用于输入"YN"

这些点当然大部分是无关紧要的——如果你编写这样的代码并且它做了你没想到的事情,同情可能会供不应求!

于 2013-07-16T19:49:30.440 回答