static const
variables are not (at least should not be) created on the stack; space for them is set aside when the program is loaded, so there should not be a runtime penalty associated with their creation.
There may be a runtime penalty associated with their initialization. although the version of gcc I'm using initializes the constant at compile time; I don't know how common that behavior is. If there is such a runtime penalty, it only occurs once at program startup.
Beyond that, any runtime performance difference between a static const
-qualified object and a literal1 (which is what a macro will eventually expand to) should be negligible to non-existent, depending on the type of the literal and the operation involved.
Stupid example (gcc version 4.1.2 20070115 (SUSE Linux)
):
#include <stdio.h>
#define FOO_MACRO 5
static const int foo_const = 5;
int main( void )
{
printf( "sizeof FOO_MACRO = %zu\n", sizeof FOO_MACRO );
printf( "sizeof foo_const = %zu\n", sizeof foo_const );
printf( " &foo_const = %p\n", ( void * ) &foo_const );
printf( "FOO_MACRO = %d\n", FOO_MACRO );
printf( "foo_const = %d\n", foo_const );
return 0;
}
Output:
sizeof FOO_MACRO = 4
sizeof foo_const = 4
&foo_const = 0x400660
FOO_MACRO = 5
foo_const = 5
Address of foo_const
is in the .rodata
section of the binary:
[fbgo448@n9dvap997]~/prototypes/static: objdump -s -j .rodata static
static: file format elf64-x86-64
Contents of section .rodata:
40065c 01000200 05000000 73697a65 6f662046 ........sizeof F
^^^^^^^^
40066c 4f4f5f4d 4143524f 203d2025 7a750a00 OO_MACRO = %zu..
40067c 73697a65 6f662066 6f6f5f63 6f6e7374 sizeof foo_const
40068c 203d2025 7a750a00 20202020 20202666 = %zu.. &f
40069c 6f6f5f63 6f6e7374 203d2025 700a0046 oo_const = %p..F
4006ac 4f4f5f4d 4143524f 203d2025 640a0066 OO_MACRO = %d..f
4006bc 6f6f5f63 6f6e7374 203d2025 640a00 oo_const = %d..
Note that the object is already initialized to 5, so there's no runtime initialization penalty.
In the printf
statements, the instruction to load the value of foo_const
into %esi
requires one more byte than the one to load the literal value 0x5
, and the instruction has to effectively dereference the %rip
register:
400538: be 05 00 00 00 mov $0x5,%esi
^^^^^^^^^^^^^^
40053d: bf ab 06 40 00 mov $0x4006ab,%edi
400542: b8 00 00 00 00 mov $0x0,%eax
400547: e8 e4 fe ff ff callq 400430 <printf@plt>
40054c: 8b 35 0e 01 00 00 mov 270(%rip),%esi # 400660 <foo_const>
^^^^^^^^^^^^^^^^^
400552: bf bb 06 40 00 mov $0x4006bb,%edi
400557: b8 00 00 00 00 mov $0x0,%eax
40055c: e8 cf fe ff ff callq 400430 <printf@plt>
Will this translate into a measurable runtime performance difference? Maybe, under the right cirucmstances. If you're doing something CPU-bound several hundred thousand times in a tight loop, then yes, using a macro (that resolves to a literal) over a static const
variable may be measurably faster. If this is something that happens once over the lifetime of the program, then the difference is too small to measure and there's no compelling reason to use the macro over the static const
variable.
As always, correctness and maintainability matter more than performance2. You're less likely to make a mistake using a static const
instead of a macro. Consider the following scenario:
#define FOO 1+2
...
x = FOO * 3;
What answer would you expect, and what answer would you get? Compare that with
static const int foo = 1+2;
...
x = foo * 3;
Yes, you could fix the macro case by using parentheses - (1 + 2)
. The point is, this scenario isn't an issue if you use the static const
object. It's one less way to shoot yourself in the foot.
1. For now, I'm only talking about simple scalar literals (integers or floats), not compound literals; haven't investigated their behavior.
2. It doesn't matter how fast your code is if it gives you the wrong answer or does the wrong thing. It doesn't matter how fast your code is if nobody can fix or upgrade it because they can't understand how it works. It doesn't matter how fast your code is if it dies at the first hint of bad input. It doesn't matter how fast your code is if it opens the door to malware.