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:28

The static means that there will be one copy of VAL created for each source file it is included in. But it also means that multiple inclusions will not result in multiple definitions of VAL that will collide at link time. In C, without the static you would need to ensure that only one source file defined VAL while the other source files declared it extern. Usually one would do this by defining it (possibly with an initializer) in a source file and put the extern declaration in a header file.

static variables at global level are only visible in their own source file whether they got there via an include or were in the main file.


Editor's note: In C++, const objects with neither the static nor extern keywords in their declaration are implicitly static.

查看更多
一纸荒年 Trace。
3楼-- · 2019-01-04 17:29

The static will mean you get one copy per file, but unlike others have said it's perfectly legal to do so. You can easily test this with a small code sample:

test.h:

static int TEST = 0;
void test();

test1.cpp:

#include <iostream>
#include "test.h"

int main(void) {
    std::cout << &TEST << std::endl;
    test();
}

test2.cpp:

#include <iostream>
#include "test.h"

void test() {
    std::cout << &TEST << std::endl;
}

Running this gives you this output:

0x446020
0x446040

查看更多
劳资没心,怎么记你
4楼-- · 2019-01-04 17:33

const variables in C++ have internal linkage. So, using static has no effect.

a.h

const int i = 10;

one.cpp

#include "a.h"

func()
{
   cout << i;
}

two.cpp

#include "a.h"

func1()
{
   cout << i;
}

If this were a C program, you would get 'multiple definition' error for i (due to external linkage).

查看更多
可以哭但决不认输i
5楼-- · 2019-01-04 17:33

The static declaration at this level of code means that the variabel is only visible in the current compilation unit. This means that only code within that module will see that variable.

if you have a header file that declares a variable static and that header is included in multiple C/CPP files, then that variable will be "local" to those modules. There will be N copies of that variable for the N places that header is included. They are not related to each other at all. Any code within any of those source files will only reference the variable that is declared within that module.

In this particular case, the 'static' keyword doesn't seem to be providing any benefit. I might be missing something, but it seems to not matter -- I've never seen anything done like this before.

As for inlining, in this case the variable is likely inlined, but that's only because it's declared const. The compiler might be more likely to inline module static variables, but that's dependent on the situation and the code being compiled. There is no guarantee that the compiler will inline 'statics'.

查看更多
在下西门庆
6楼-- · 2019-01-04 17:42

const variables are by default static in C++, but extern C. So if you use C++ this no sense what construction to use.

(7.11.6 C++ 2003, and Apexndix C has samples)

Example in compare compile/link sources as C and C++ program:

bruziuz:~/test$ cat a.c
const int b = 22;
int main(){return 0;}
bruziuz:~/test$ cat b.c
const int b=2;
bruziuz:~/test$ gcc -x c -std=c89 a.c b.c
/tmp/ccSKKIRZ.o:(.rodata+0x0): multiple definition of `b'
/tmp/ccDSd0V3.o:(.rodata+0x0): first defined here
collect2: error: ld returned 1 exit status
bruziuz:~/test$ gcc -x c++ -std=c++03 a.c b.c 
bruziuz:~/test$ 
bruziuz:~/test$ gcc --version | head -n1
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609
查看更多
Juvenile、少年°
7楼-- · 2019-01-04 17:42

Static prevents another compilation unit from externing that variable so that the compiler can just "inline" the variable's value where it is used and not create memory storage for it.

In your second example, the compiler cannot assume that some other source file won't extern it, so it must actually store that value in memory somewhere.

查看更多
登录 后发表回答