我在某些语言中知道以下内容:

a += b

比以下方法更有效:
a = a + b

因为它消除了创建临时变量的需要。在C中是这种情况吗?使用+ =是否更有效(因此,还有-= *=等)

最佳答案

所以这是一个明确的答案...

$ cat junk1.c
#include <stdio.h>

int main()
{
    long a, s = 0;
    for (a = 0; a < 1000000000; a++)
    {
        s = s + a * a;
    }
    printf("Final sum: %ld\n", s);
}

michael@isolde:~/junk$ cat junk2.c
#include <stdio.h>

int main()
{
    long a, s = 0;
    for (a = 0; a < 1000000000; a++)
    {
        s += a * a;
    }
    printf("Final sum: %ld\n", s);
}

michael@isolde:~/junk$ for a in *.c ; do gcc -O3 -o ${a%.c} $a ; done
michael@isolde:~/junk$ time ./junk1
Final sum: 3338615082255021824

real    0m2.188s
user    0m2.120s
sys 0m0.000s
michael@isolde:~/junk$ time ./junk2
Final sum: 3338615082255021824

real    0m2.179s
user    0m2.120s
sys 0m0.000s

...对于我的计算机和我的编译器,它们在我的操作系统上运行。您的结果可能会有所不同,也可能不会有所不同。但是,在我的系统上,时间是相同的:用户时间为2.120s。

现在只是为了向您展示现代编译器的性能,您会注意到我在赋值中使用了a * a表达式。这是由于这个小问题:
$ cat junk.c
#include <stdio.h>

int main()
{
    long a, s = 0;
    for (a = 0; a < 1000000000; a++)
    {
        s = s + a;
    }
    printf("Final sum: %ld\n", s);
}

michael@isolde:~/junk$ gcc -O3 -S junk.c
michael@isolde:~/junk$ cat junk.s
    .file   "junk.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "Final sum: %ld\n"
    .text
    .p2align 4,,15
.globl main
    .type   main, @function
main:
.LFB22:
    .cfi_startproc
    movabsq $499999999500000000, %rdx
    movl    $.LC0, %esi
    movl    $1, %edi
    xorl    %eax, %eax
    jmp __printf_chk
    .cfi_endproc
.LFE22:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits

编译器找出了我的循环,并将其展开到计算累积总和的位置,然后将其嵌入为一个常量,继续打印出来,从而完全跳过了任何一种循环构造。面对如此聪明的优化器,您真的认为您将在区分s = s + as += a时找到任何有意义的优势吗?

10-02 22:44