哪个更快:增量或带加法运算的方程式

Which is faster: Increment or equation with addition arithmetic

示例:

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

假设abcd每一个都被完全同时调用,先执行哪一个?

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

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

使用 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的版本好像都一样

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

编译器不会盲目地读取代码并为每个语句生成一些指令,编译器根据标准推理代码的结果应该是什么,并生成整个程序运行所需的代码按要求。因此,询问有关单个语句的性能问题几乎总是毫无意义的。让我举个例子:

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; }

哪个更快?函数 foo 还是 bar?许多人会说 "of course multiplication is slower",但最有可能的答案是:两者都同样快,因为一个非常简单的死存储优化会发现没有使用 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,它只是来自函数的 returns。

在编程中,一元运算符比其他运算符具有更高的优先级。一元运算符在其他运算符执行之前执行。 Pre 和 Post 增量运算符是一元运算符的示例,而 c 和 d 是二元运算符,因此执行 later.Also c 只是 d 的简写符号,因此两者都需要相同的时间并且来自a 和 b,a 比 b 执行得早,因为 post increment 比 pre increment 快。 希望这个回答对您有所帮助。