Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I know in some languages the following:

a += b

is more efficient than:

a = a + b

because it removes the need for creating a temporary variable. Is this the case in C? Is it more efficient to use += (and, therefore also -= *= etc)

like image 761
robintw Avatar asked Feb 17 '11 16:02

robintw


1 Answers

So here's a definitive answer...

$ 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

...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 <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

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?!

like image 90
JUST MY correct OPINION Avatar answered Sep 28 '22 00:09

JUST MY correct OPINION