我听到很多人说
int a = 0;
a += 10;
比
快int a = 0;
a = a + 10;
为什么?我用gdb调试它,它绝对是相同的指令。
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.
那么为什么“(变量)+ =(值)”比“(变量)=(变量)+(值)”更快?
答案 0 :(得分:8)
它并不快。如您所见,生成的程序集完全相同。无论谁告诉你一个人,编造故事的速度要快得多。
答案 1 :(得分:6)
正如其他人所说,在这种情况下并不重要。但是,有一些相似但非常不同的情况:
int *f(void);
(*f()) = (*f()) + 1;
(*f()) += 1;
在第2行,f()
被调用两次,在第3行只调用一次。
int * volatile *p;
**p = **p + 1;
**p += 2;
在第二行中,编译器将读取*p
两次,假设它可能在访问之间发生变化(并且您将读取一个地方,另一个地方写入)。在第3个中,它会读取*p
一次并增加此位置。
如果你感到顽皮:
#define a *f()
int a;
a = a + 1;
a++;
看起来几乎与问题完全一样,但表现得像我的第一个例子。
答案 2 :(得分:3)
我认为你刚刚证明了对于你正在使用的c编译器来说它并不快。但是,您可能在编译期间运行了优化。此外,其他编译器也可能不会这样做。
答案 3 :(得分:2)
我认为“更快”意味着它更容易输入a += 10
而不是a = a + 10
。两者完全相同。
答案 4 :(得分:1)
您必须在编译器的基础上逐个编译,并逐个选项。未优化它可能生成不同的代码,但同时未经优化的可能会慢得多,即使对于这一行代码也是如此。真正的答案与编译器内部有关,你可以通过clang / llvm看到它们很简单,但也许与gcc和其他人一样。当它生成汇编时,它就会顺利进行,编译器往往会有一个内部通用代码进行一些优化,然后最终转换为汇编/机器代码进一步针对特定目标进行优化。您的问题的有趣答案是编译器前端对这两个微妙的不同代码行做了什么?如果不是从一开始就在那一点上加入并在组装/机器代码输出的路上或途中变成相同的结果?
答案 5 :(得分:0)
没有。你的信息不正确。这两条指令都占用了同一时间。
两者
int a = 0;
a += 10;
和
int a = 0;
a = a + 10;
生成相同的汇编代码并具有相同的速度。