简体   繁体   中英

Why is one assignment faster than the other?

I heard a lot people saying

int a = 0;
a += 10;

is faster than

int a = 0;
a = a + 10;

Why is that? I debugged it with gdb and it was absolutely the same instructions.

gdb :

First

(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.

Second

(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.

So why is "(variable) += (value)" faster than "(variable) = (variable) + (value)" ?

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

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.

I think you just proved that it is not faster at all for whichever c compiler you are using. However, you may have optimizations running during the compile. Also, other compilers may not do that the same way.

I think what they meant by "faster" is that its easier to type a += 10 than a = a + 10 . Both are completely identical otherwise.

You have to look at this on a compiler by compiler basis, and option by option. Unoptimized it might generate different code, but at the same time unoptimized is going to likely be much slower even for this single one line of code. The real answer has to do with the compiler internals which you can see really easy with clang/llvm, but maybe with gcc and others. By the time it generates assembly it is well down the road, compilers tend to have an internal generic code that gets some optimization then the final conversion to assembly/machine code has further target specific optimization. The interesting answer to your question is what does the compiler frontend do with those two subtle different lines of code? If not from the very beginning at what point do those two join and become the same result at or on the way to the assembly/machine code output?

No. You had incorrect information. Both the instructions take up the same time.

Both

int a = 0;
a += 10;

and

int a = 0;
a = a + 10;

generate the same assembly code and are having equal speed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM