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?
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 .
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.
“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.
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.
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.
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.
“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.
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.
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.
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 #,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With