Variable declarations in header files - static or

2019-01-04 16:57发布

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?

标签: c++ c static
12条回答
欢心
2楼-- · 2019-01-04 17:16

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.

In C, file-scoped variables are extern by default. If you're using C, VAL is static and ANOTHER_VAL is extern.

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

In C++, file-scoped variables are static by default if they are const, and extern by default if they are not. If you're using C++, both VAL and ANOTHER_VAL are static.

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...

  • debug options
  • address taken in the file
  • compiler always allocates storage (complex const types can't easily be inlined, so becomes a special case for basic types)
查看更多
劳资没心,怎么记你
3楼-- · 2019-01-04 17:22

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.

查看更多
Viruses.
4楼-- · 2019-01-04 17:24

The static and extern 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 or extern) 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 is static and ANOTHER_VAL is extern.

  • In C++, file-scoped variables are static (internal linkage) by default if they are const, and extern by default if they are not. If you're using C++, both VAL and ANOTHER_VAL are static.

From a draft of the C specification:

6.2.2 Linkages of identifiers ... -5- If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

From a draft of the C++ specification:

7.1.1 - Storage class specifiers [dcl.stc] ... -6- A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has internal linkage because of a previous declaration and provided it is not declared const. Objects declared const and not explicitly declared extern have internal linkage.

查看更多
冷血范
5楼-- · 2019-01-04 17:24

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

查看更多
乱世女痞
6楼-- · 2019-01-04 17:26

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.

查看更多
欢心
7楼-- · 2019-01-04 17:26

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.

查看更多
登录 后发表回答