i = i + j之间有什么区别;和i + = j;用c语言?

时间:2013-07-16 18:02:34

标签: c gcc

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

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

6 个答案:

答案 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 += ji = i + j不同,因为i本身有side effect
还有一个问题是operator precedence,即

i = i * j + k;

不同
i *= j + k;  

答案 3 :(得分:2)

两个语句i = i + ji += 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)

Syntactic sugar baby。

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

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

答案 5 :(得分:1)

在这两种情况下i(要分配的变量或表达式)必须是左值。在大多数情况下,只要i未声明为volatile,这将产生两种情况相同的代码。

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

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

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

不太合理的情况是使用条件运算符表达式作为左值。例如,以下内容将j添加到bc,具体取决于a

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

这些可能会生成不同的代码 - 编译器可能无法找到该成语并应用优化。如果表达式a有副作用 - 例如表达式getchar() == '\n'avolatile(无论b还是c),然后它们不等同,因为第二个会评估为:

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

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