Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 428
user3282276 Avatar asked Nov 21 '14 18:11

user3282276


People also ask

Should I use const or static?

You want to use const when you have a variable whose value will not change, ever, during the time your application is being used. Further, any variable declared as const will also, implicitly, be declared static .

Is it static const or const static?

They mean exactly the same thing. You're free to choose whichever you think is easier to read. In C, you should place static at the start, but it's not yet required.

Can static be const?

“static const” is basically a combination of static(a storage specifier) and const(a type qualifier). The static determines the lifetime and visibility/accessibility of the variable.

Can we use static const in C?

const means that you're not changing the value after it has been initialised. static inside a function means the variable will exist before and after the function has executed. static outside of a function means that the scope of the symbol marked static is limited to that . c file and cannot be seen outside of it.

What is the difference between static and const in JavaScript?

A static keyword is been used to declare a variable or a method as static. A const keyword is been used to assign a constant or a fixed value to a variable. In JavaScript, the static keyword is used with methods and classes too. In JavaScript, the const keyword is used with arrays and objects too.

What is the difference between static methods and const variables?

The static methods are basically utility functions creating or making a copy of an object. The const variable is basically used for declaring a constant value that cannot be modified. A static keyword is been used to declare a variable or a method as static. A const keyword is been used to assign a constant or a fixed value to a variable.

What is “static const”?

“static const” is basically a combination of static (a storage specifier) and const (a type qualifier). The static determines the lifetime and visibility/accessibility of the variable.

What is the difference between static const and static const in Python?

These three are often confusing and choosing which one to use can sometimes be a difficult task. static const : “static const” is basically a combination of static (a storage specifier) and const (a type qualifier). Static : determines the lifetime and visibility/accessibility of the variable.


2 Answers

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.

like image 83
Venkatesh Avatar answered Sep 22 '22 07:09

Venkatesh


The quick way to test simple optimization questions is to use godbolt.

For your specific issue a modern optimizing compiler should be able to produce the same code for both cases and will in fact just optimize them away to a constant. We can see this with the following program (see it live):

#include <stdio.h>  #define CONSTANT 6 static const int  constant = 6;  void func() {   printf( "%d\n", constant ) ;   printf( "%d\n", CONSTANT ) ; } 

in both cases both accessing reduce to the following:

movl    $6, %esi    #, 
like image 35
Shafik Yaghmour Avatar answered Sep 22 '22 07:09

Shafik Yaghmour