"Static const" vs "#define" for efficiency in C

c, c-preprocessor, constants, performance

Solution

Consider the following 2 test files

Test1.c: Uses static const foo.

// Test1.c uses static const..

#include <stdio.h>

static const foo = 6;

int main() {
    printf("%d", foo);
    return 0;
}

Test2.c: uses macro.

// Test2.c uses macro..

#include <stdio.h>

#define foo 6

int main() {
    printf("%d", foo);
    return 0;
}

and the corresponding assembly equivalences when using `gcc -O0`(default) are follows,

Assembly for Test1.c:

  0000000000000000 <main>:
   0:   55                      push   rbp
   1:   48 89 e5                mov    rbp,rsp
   4:   48 83 ec 20             sub    rsp,0x20
   8:   e8 00 00 00 00          call   d <main+0xd>
   d:   b8 06 00 00 00          mov    eax,0x6
  12:   89 c2                   mov    edx,eax
  14:   48 8d 0d 04 00 00 00    lea    rcx,[rip+0x4]        # 1f <main+0x1f>
  1b:   e8 00 00 00 00          call   20 <main+0x20>
  20:   b8 00 00 00 00          mov    eax,0x0
  25:   48 83 c4 20             add    rsp,0x20
  29:   5d                      pop    rbp
  2a:   c3                      ret
  2b:   90                      nop

Assembly for Test2.c:

  0000000000000000 <main>:
   0:   55                      push   rbp
   1:   48 89 e5                mov    rbp,rsp
   4:   48 83 ec 20             sub    rsp,0x20
   8:   e8 00 00 00 00          call   d <main+0xd>
   d:   ba 06 00 00 00          mov    edx,0x6
  12:   48 8d 0d 00 00 00 00    lea    rcx,[rip+0x0]        # 19 <main+0x19>
  19:   e8 00 00 00 00          call   1e <main+0x1e>
  1e:   b8 00 00 00 00          mov    eax,0x0
  23:   48 83 c4 20             add    rsp,0x20
  27:   5d                      pop    rbp
  28:   c3                      ret
  29:   90                      nop

In both the cases, it is not using external memory. But the difference is that, `#define` replaces `foo` by the value, `static const` is an instruction so it increments the instruction pointer to the next instruction and it uses 1 additional register to store the value.

By this, we can say that macro is better than static constants but the difference is minimum.

EDIT: When using `-O3` compilation option (i.e at optimization on) both the test1.c and test2.c evaluates the same.

0000000000000000 <main>:
   0:   48 83 ec 28             sub    rsp,0x28
   4:   e8 00 00 00 00          call   9 <main+0x9>
   9:   48 8d 0d 00 00 00 00    lea    rcx,[rip+0x0]        # 10 <main+0x10>
  10:   ba 06 00 00 00          mov    edx,0x6
  15:   e8 00 00 00 00          call   1a <main+0x1a>
  1a:   31 c0                   xor    eax,eax
  1c:   48 83 c4 28             add    rsp,0x28
  20:   c3                      ret
  21:   90                      nop

So, `gcc` treats both `static const` and `#define` as the same when it optimize.

Problem

I was recently wondering what the difference between `#define` and `static const` is in C and why two methods exist to do the same things. I found some people that had similar questions here: Advantage and disadvantages of #define vs. constants? "static const" vs "#define" vs "enum" static const vs #define Lots of people talk about best practice and convention as well as give practical reasons for using one over the other, such as the need to pass a pointer to a constant, which I can do with a `static const` but not with a `#define`. However I have yet to find anyone talk about a comparison of the efficiency of the two. From what I understand about the C preprocessor, if I have a statement like this: ``` #define CONSTANT 6 ``` I create a constant value that can be used like this `char[CONSTANT]` which will actually be replaced with this statement `char[6]` prior to actually being compiled. This to me seems like it would be more efficient than using a `static const constant = 6;` because this would create a variable called constant that would live on the stack which I assume would come with some more baggage than a `#define`. Assuming I need a constant in a situation where I could choose to use either a preprocessor `#define` or a `static const` statement with no obvious reasons to choose one over the other, which is more efficient? And how exactly would I go about testing this myself?

Original source

Related problems