1

我听到很多人说

int a = 0;
a += 10;

int a = 0;
a = a + 10;

这是为什么?我用 gdb 调试了它,它是完全一样的指令。

数据库:

第一的

(gdb) list
1   int main()
2   {
3       int counter = 0;
4       counter = counter + 10;
5       return 0;
6   }
(gdb) disassemble main
Dump of assembler code for function main:
   0x00000000004004cc <+0>: push   %rbp
   0x00000000004004cd <+1>: mov    %rsp,%rbp
   0x00000000004004d0 <+4>: movl   $0x0,-0x4(%rbp)
   0x00000000004004d7 <+11>:    addl   $0xa,-0x4(%rbp)
=> 0x00000000004004db <+15>:    mov    $0x0,%eax
   0x00000000004004e0 <+20>:    pop    %rbp
   0x00000000004004e1 <+21>:    retq   
End of assembler dump.

第二

(gdb) list
1   int main()
2   {
3       int counter = 0;
4       counter += 10;
5       return 0;
6   }

(gdb) disassemble main
Dump of assembler code for function main:
   0x00000000004004cc <+0>: push   %rbp
   0x00000000004004cd <+1>: mov    %rsp,%rbp
   0x00000000004004d0 <+4>: movl   $0x0,-0x4(%rbp)
   0x00000000004004d7 <+11>:    addl   $0xa,-0x4(%rbp)
=> 0x00000000004004db <+15>:    mov    $0x0,%eax
   0x00000000004004e0 <+20>:    pop    %rbp
   0x00000000004004e1 <+21>:    retq   
End of assembler dump.

那么为什么 "(variable) += (value)" 比 "(variable) = (variable) + (value)" 快呢?

4

6 回答 6

8

It's not faster. As you see, the generated assembly is identical. Whoever told you one is faster was making up stories.

于 2013-06-10T17:14:27.790 回答
6

As others said, in this case it doesn't matter. However, there are some similar but very different cases:

int *f(void);
(*f()) = (*f()) + 1;
(*f()) += 1;

In the 2nd line, f() is called twice, in the 3rd line just once.

int * volatile *p;
**p = **p + 1;
**p += 2;

In the 2nd line, the compiler will read *p twice, assuming it may change between accesses (and you'd be reading one place, writing another). In the 3rd, it will read *p once and increment this place.

And if you're feeling naughty:

#define a *f()
int a;
a = a + 1;
a++;

Looks almost exactly as in the question, but behaves like my first example.

于 2013-06-10T18:30:13.713 回答
3

我认为您刚刚证明,无论您使用哪种 c 编译器,它都不会更快。但是,您可能会在编译期间运行优化。此外,其他编译器可能不会这样做。

于 2013-06-10T17:16:23.777 回答
2

我认为他们所说的“更快”的意思是它a += 10a = a + 10. 两者在其他方面完全相同。

于 2013-06-10T17:18:17.547 回答
1

您必须逐个编译器并逐个选项地查看此编译器。未优化它可能会生成不同的代码,但与此同时,即使对于这一行代码,未优化也可能会慢得多。真正的答案与编译器内部有关,使用 clang/llvm 可以很容易地看到,但可能使用 gcc 和其他。到它生成程序集的时候,它已经很顺利了,编译器往往有一个内部通用代码,可以得到一些优化,然后最终转换为程序集/机器代码有进一步的目标特定优化。您的问题的有趣答案是编译器前端对这两条微妙的不同代码行做了什么?如果不是从一开始,这两个在什么时候加入并在汇编/机器代码输出的途中或途中成为相同的结果?

于 2013-06-10T17:37:31.060 回答
0

不,您的信息不正确。两条指令占用相同的时间。

两个都

int a = 0;
a += 10;

int a = 0;
a = a + 10;

生成相同的汇编代码并具有相同的速度。

于 2013-06-10T17:16:58.117 回答