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

时间:2015-07-23 14:13:47

标签: c performance math increment addition

示例:

a : ++i;
b : i++;
c : i += 1;
d : i = i + 1;

假设每个abcd被完全同时调用,其中一个将首先被执行?

4 个答案:

答案 0 :(得分:9)

使用gcc 5.2编译该程序:

#include<stdio.h>

int main()
{
    int i = 0;
    ++i;
    i++;
    i += 1;
    i = i + 1;
    return 0;
}

它给出了这个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

这意味着与gcc 5.2 它的执行速度完全相同。

从4.4.7到5.2的版本似乎是一样的。

答案 1 :(得分: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; }

哪一个更快?功能foobar?很多人会说“当然乘法速度较慢”,但很可能答案是:两者都同样快,因为非常简单的死存储优化会发现没有使用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

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

答案 2 :(得分:1)

现代编译器足够聪明,可以优化所有这四种情况以提高性能。

您应该注意,在最后一个表达式i = i+1中,i将被评估两次。

答案 3 :(得分:0)

在编程中,一元运算符的优先级高于其他运算符。一元运算符在执行其他运算符之前执行。前后增量运算符是一元运算符的例子,而c和d是二元运算符,因此后面执行。也就是c只是d的简写符号,因此两者都需要相同的时间,而a和b,a是在b之前执行,因为后增量比预增量快。 我希望这个答案有所帮助。