Is a += b more efficient than a = a + b in C?

前端 未结 7 1725
耶瑟儿~
耶瑟儿~ 2020-12-10 04:42

I know in some languages the following:

a += b

is more efficient than:

a = a + b

because it removes the n

7条回答
  •  一生所求
    2020-12-10 05:13

    So here's a definitive answer...

    $ cat junk1.c
    #include 
    
    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 
    
    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
    

    ...for my computer and my compiler running on my operating system. Your results may or may not vary. On my system, however, the time is identical: user time 2.120s.

    Now just to show you how impressive modern compilers can be, you'll note that I used the expression a * a in the assignment. This is because of this little problem:

    $ cat junk.c
    #include 
    
    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
    

    The compiler figured out my loop and unrolled it to the point of calculating the cumulative sum and just embedded that as a constant which it proceeded to print out, skipping any kind of looping construct entirely. In the face of optimizers that clever do you really think you're going to find any meaningful edge in distinguishing between s = s + a and s += a?!

提交回复
热议问题