2013-07-16 81 views
3

i = i + j有什么区别?和i += j;在C? 它们是否等同?有没有i的副作用?i = i + j有什么区别;和i + = j;在C语言?

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

+0

这2条线本身是相同的,不管是我还是j的类型。如果您在同一个语句中添加了其他任何内容,则优先顺序可能会改变结果答案。也就是说,我看到一些“不太好”的编译器为它们输出不同的汇编器。去图:) –

+1

检查汇编代码,你可能会发现有趣的细节什么卡尔的回答。 –

+3

查看http://stackoverflow.com/questions/5031604/is-a-b-more-efficient-than-a-a-b-in-c – mizo

回答

8

它们几乎相同。唯一的区别是i仅在+=的情况下评估一次,而在另一种情况下则为两次。

+1

而'i + = j'更具可读性:) – VoidPointer

+0

'i'必须在第二种情况下评估两次,而不是第一次?我并不完全遵循你的逻辑,并且很想听听你是怎么想出来的。 –

+5

@MichaelDorgan通常它不会有问题(因为'i'会填入某个寄存器中,所以会被优化),但是如果'i'是易失性的并且被其他线程或中断修改,可能会引起关注。希望_still_无关紧要,因为你已经适当地确保[互斥](http://en.wikipedia.org/wiki/Mutual_exclusion),以便只有一个执行单元一次访问它。 –

4

i = i + j相当于i += j但不相同
在某些情况下(罕见)i += ji = i + j不同,因为i本身有一个side effect
还多了一个问题是operator precedence

i = i * j + k; 

不一样

i *= j + k; 
+2

最完整的答案,+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

两种说法i = i + ji += j,在功能上相同,在第一种情况下,你使用的是一般的赋值操作,而第二个使用combinatorial assignment operator+=additive assignment operator(添加后跟赋值)。 组合赋值运算符的使用生成smaller source codeless susceptible to maintenance errors,也可能是smaller object code,运行速度也会更快。 Compilation is also likely to be a little faster

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'avolatile(不管bc),那么它们不是等效由于第二将评估为:

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

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

相关问题