When refactoring away some #defines
I came across declarations similar to the following in a C++ header file:
static const unsigned int VAL = 42;
const unsigned int ANOTHER_VAL = 37;
The question is, what difference, if any, will the static make? Note that multiple inclusion of the headers isn't possible due to the classic #ifndef HEADER
#define HEADER
#endif
trick (if that matters).
Does the static mean only one copy of VAL
is created, in case the header is included by more than one source file?
To answer the question, "does the static mean only one copy of VAL is created, in case the header is included by more than one source file?"...
NO. VAL will always be defined separately in every file that includes the header.
The standards for C and C++ do cause a difference in this case.
Note that Modern linkers may complain about ANOTHER_VAL if the header is included in different files (same global name defined twice), and would definitely complain if ANOTHER_VAL was initialised to a different value in another file
You also need to take account of the fact that both variables are designated const. Ideally the compiler would always choose to inline these variables and not include any storage for them. There is a whole host of reasons why storage can be allocated. Ones I can think of...
Static prevents the compiler from adding multiple instances. This becomes less important with #ifndef protection, but assuming the header is included in two seperate libraries, and the application is linked, two instances would be included.
The
static
andextern
tags on file-scoped variables determine whether they are accessible in other translation units (i.e. other.c
or.cpp
files).static
gives the variable internal linkage, hiding it from other translation units. However, variables with internal linkage can be defined in multiple translation units.extern
gives the variable external linkage, making it visible to other translation units. Typically this means that the variable must only be defined in one translation unit.The default (when you don't specify
static
orextern
) is one of those areas in which C and C++ differ.In C, file-scoped variables are
extern
(external linkage) by default. If you're using C,VAL
isstatic
andANOTHER_VAL
isextern
.In C++, file-scoped variables are
static
(internal linkage) by default if they areconst
, andextern
by default if they are not. If you're using C++, bothVAL
andANOTHER_VAL
arestatic
.From a draft of the C specification:
From a draft of the C++ specification:
The C book (free online) has a chapter about linkage, which explains the meaning of 'static' in more detail (although the correct answer is already given in other comments): http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html
You can’t declare a static variable without defining it as well (this is because the storage class modifiers static and extern are mutually exclusive). A static variable can be defined in a header file, but this would cause each source file that included the header file to have its own private copy of the variable, which is probably not what was intended.
Assuming that these declarations are at global scope (i.e. aren't member variables), then:
static means 'internal linkage'. In this case, since it is declared const this can be optimised/inlined by the compiler. If you omit the const then the compiler must allocate storage in each compilation unit.
By omitting static the linkage is extern by default. Again, you've been saved by the constness - the compiler can optimise/inline usage. If you drop the const then you will get a multiply defined symbols error at link time.