If I never use the address of a static const variable, is memory allocated for it when using a reasonably modern compiler?
-
5Which compiler? You can also answer this by looking at the assembly output from your compiler. – Greg Hewgill Nov 28 '11 at 00:03
-
No particular compiler, use the lowest common denominator in answering the question. I don't write code for a certain compiler, I try to write code that will behave mostly the same in all modern widely used compilers. – Emil Eriksson Nov 28 '11 at 09:23
4 Answers
It depends on the type of the variable, and on whether "constant" also means "constant expression". Example:
static const Foo = get_foo(std::cin);
static const int q = argc * 3;
static const std::string s(gets());
These variables are const, but blatantly need an actual allocation.
On the other hand, the following constant expression may never have physical storage:
static const int N = 1000;
static const std::shared_ptr<void> vp(); // constexpr constructor!
Most importantly, static constexpr member variables don't need a definition if you're careful:
struct Bar
{
int size() const { return N; }
static const int N = 8;
};
// does NOT need "const int Bar::N;"

- 464,522
- 92
- 875
- 1,084
-
2The second example (`q`) might not need a memory location, depending on where it gets used. – Oliver Charlesworth Nov 28 '11 at 00:06
-
1The reason I'm asking, as you might have guessed, is because I'm wondering if a #define could be replaced by a static const even in a tiny embedded environment where every byte counts. – Emil Eriksson Nov 28 '11 at 09:24
-
@EmilEriksson: Now you're getting somewhere. If you're working in a "tiny embedded environment", then change your code and look at the output. You are using a specific compiler. Different compilers may make different choices that (should) produce the same results. – Greg Hewgill Nov 29 '11 at 20:36
-
@EmilEriksson: Well, don't put the definition in! If it compiles and links, you're sorted. If for some reason someone insists on having a definition, you can consider your macro alternative. – Kerrek SB Nov 29 '11 at 20:38
-
@KerrekSB. I had a similar question and I upvoted the answer because, it kinda answer it. But, I still would like to know on what circumstances, " constant expression may have physical storage " ?? I stopped compilation with -S to see assembly code for my arm-linux-gcc and I was able to see the object name which is initialized in-class with constant expression, say `N` in this case, in the `.s` file – smRaj Oct 03 '14 at 09:15
-
@smRaj: Physical storage is required when the variable that is declared as a constant expression is "odr used", for example if you take its address. – Kerrek SB Oct 03 '14 at 09:50
-
@KerrekSB : Appreciate the speedy response for an OLDER post. I don't see many do that. Coming to the topic, in my class its reference is not taken and still the variable name I could see in the arm-linux-gcc assembly output and if I use #define, I don't see the variable name. Just because I see the variable name in the arm-linux-gcc assembly output. Is it okay to assume that the variable is allocated memory? – smRaj Oct 03 '14 at 10:31
-
@KerrekSB: What I see in my arm-linux-gcc assembly output `.s` file is something like `.LASF1730: .ascii "BUF_SIZE\000"` and then somewhere else in the `.s` file, I see `.4byte .LASF1730` Where `BUF_SIZE` is the static const integer which is initialized in-class and whose address is never used in the class implementation file. Only used in three places; 1)Array sizing `char arrayName[BUF_SIZE]` 2) `memset()` call, third parameter 3) `read()` call third parameter. I would assume all of these are not odr-used – smRaj Oct 03 '14 at 10:42
-
@smRaj: I'm not sure whether an actual problem exists. Of course the actual *value* of the constant expression has to appear somewhere in your machine code, whether you use a variable for that or not, and your value is an arbitrary byte string. If use use a macro, the value is just going to be somewhere else, perhaps under some different name. Try the same with an `int` constant and see if you have the same problem. – Kerrek SB Oct 03 '14 at 12:45
-
@KerrekSB My constant is an integer only. Class header file has `static const int BUF_SIZE = 1024;` and class implementation uses `BUF_SIZE` as I mentioned in my above comment. – smRaj Oct 06 '14 at 09:57
-
@smRaj: Are you sure this isn't a debug symbol or some such? Why would it be `.ascii "BUF_SIZE\000"` for an integer? – Kerrek SB Oct 06 '14 at 10:33
-
@KerrekSB : I removed the debug symbols and I no more see BUF_SIZE in the `arm-linux-gcc` assembly output. But, I am still not sure how do I know if the memory is allocated for that (static const in-class initialized integer whose address is never taken) or not ??? – smRaj Oct 09 '14 at 11:30
-
I don't see any evidence that things like `static const int q = argc * 3;` need an allocation. It depends on how you use `q` and the implementation details of your compiler. – David Grayson May 06 '18 at 09:02
-
@DavidGrayson: I was probably referring to the entire example block, where it's the strings that require allocations, not the int. Const ints may indeed be used as constant expressions if suitably initialized. Past me wasn't very good at C++ though. – Kerrek SB May 06 '18 at 09:24
There is chance that it isn't, but that doesn't matter. You can't rely on implementation details, only on the standard.

- 33,961
- 14
- 109
- 164

- 23,169
- 18
- 105
- 180
-
2So what DOES the standard say about the allocation of space for "static const" declarations ? – Ingo Blackman Nov 26 '13 at 23:29
-
1The point is that the presence of a variable in memory can be considered an implementation detail since (in this case) it doesn't affect the behavior of the program. So valid C compilers, compiling the same program, can make different choices about what goes into memory. – David Grayson May 06 '18 at 08:59
In practice, space for static storage can be allocated as part of the initial binary loading, or by the runtime during startup; but will always happen before user code is encountered.
In addition to the constraints that Kerrek SB mentions, the storage for a const expr
value could be eliminated if the value itself is never used at runtime.
This wouldn't necessarily mean that the value needs to not be evaluated - if a static const expr
were only used as a branch condition, that condition may be evaluated statically and other code paths may not be generated or may be excluded by the optimiser.
Pretty much any storage with static
duration may be eliminated if the implementation can guarantee behaviour as though the storage were present - i.e. a comparison expression that can be evaluated at compile time - like a different const expr
, a pointer comparison where the rhs is known to be an alias to a different variable, or perhaps an incompatible type. It may also be eliminated if the value is only read into variables that are never read themselves; or where the value may be reduced to a const expr
.
struct Foo{};
static Foo bar; // static instance
Foo* func() {
if ( ! (&bar) ) { // always non-NULL
// this block may be eliminated
Foo* myCopy(new Foo(bar));
return myCopy;
}
// so 'bar' is never referred to, and we know it has no side-
// effects, so the static variable can be eliminated
return new Foo();
}
3.7.1 Static storage duration
2.
If an object of static storage duration has initialization or a destructor with side effects, it shall not be eliminated even if it appears to be unused, except that a class object or its copy may be eliminated as specified in 12.8.

- 2,652
- 1
- 25
- 31
Memory for global variables is reserved by the linker, not the compiler. So the question is whether the linker is smart enough to not reserve space for global variables that are only used by value.
It depends on the type and use of such data; for example, floating point constants generally must be loaded from memory, so they must have storage even if you don't directly use the address.
Having said that, the standard does specify whether you can optimize out static storage (3.7.1.2: [basic.stc.static]):
If a variable with static storage duration has initialization or a destructor with side effects, it shall not be eliminated even if it appears to be unused, except that a class object or its copy/move may be eliminated as specified in 12.8.
So if the static const variable has a constructor or destructor, it cannot be optimized out (although some compilers/linkers will do this anyway). If it doesn't, it can. Whether it will depends on the linker.

- 53,214
- 7
- 75
- 105
-
1Memory is reserved by both the compiler and the linker. Either is capable of eliminating unused data. The compiler can only reasonably do so for `static` variables, but that is what the question is about anyway. – Dietrich Epp Nov 28 '11 at 02:03