哪个更快:使用加法算法增加或等式

Imo*_*lis -1 c math performance increment addition

例:

a : ++i;
b : i++;
c : i += 1;
d : i = i + 1;
Run Code Online (Sandbox Code Playgroud)

假设每个abcd被称为完全同步,其中一个将首先执行?

Tho*_*oub 9

使用gcc 5.2编译这个程序:

#include<stdio.h>

int main()
{
    int i = 0;
    ++i;
    i++;
    i += 1;
    i = i + 1;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它给出了这个ASM:

main:
    push    rbp
    mov rbp, rsp
    mov DWORD PTR [rbp-4], 0
    add DWORD PTR [rbp-4], 1 #++i
    add DWORD PTR [rbp-4], 1 #i++
    add DWORD PTR [rbp-4], 1 #i += 1
    add DWORD PTR [rbp-4], 1 #i = i + 1
    mov eax, 0
    pop rbp
    ret
Run Code Online (Sandbox Code Playgroud)

这意味着使用gcc 5.2,它的执行速度完全相同.


对于从4.4.7到5.2的版本,它似乎是相同的.


Art*_*Art 5

在这个特定的例子中,所有四个表达式都具有完全相同的外部可观察结果,因此有能力的编译器应该为它们生成完全相同的代码.

编译器不会盲目地读取代码并为每个语句生成一些指令,编译器会根据标准推断代码的结果,并生成整个程序根据需要运行所需的代码.因此,询问关于单个陈述的表现问题几乎总是毫无意义.让我举个例子:

void foo(unsigned int a, unsigned int b) { unsigned int i = a * b; }
void bar(unsigned int a, unsigned int b) { unsigned int i = a + b; }
Run Code Online (Sandbox Code Playgroud)

哪一个更快?功能foo还是bar?许多人会说"当然乘法更慢",但很可能答案是:两者都同样快,因为非常简单的死存储优化会看到没有用i,所以不需要计算它,所以编译器可以优化函数一无所获.我们来试试吧:

$ cat > foo.c
void foo(unsigned int a, unsigned int b) { unsigned int i = a * b; }
void bar(unsigned int a, unsigned int b) { unsigned int i = a + b; }
$ cc -S -fomit-frame-pointer -O2 foo.c
$ cat foo.s
[... I edited out irrelevant spam to make this more readable ...]
_foo:                                   ## @foo
    retq

_bar:                                   ## @bar
    retq
Run Code Online (Sandbox Code Playgroud)

两个函数中唯一的指令retq只是从函数返回.