undefined reference to array of constants

2019-04-06 18:54发布

问题:

a.cpp

const unsigned char whatever[123] = { /* ... */ };

a.h

extern const unsigned char whatever[123];

b.cpp

#include "a.h"
unsigned char x = whatever[0];
// error: undefined reference to 'whatever'

Why do I get an undefined reference error? Without the const, the error goes away.

How do I share an array of constants among multiple translation units?

回答1:

This is one of the quirks people run into, it's simply a matter that you've defined an a.h header file which declares a const array of 123 chars, and assigned it external linkage. When it is included into the b.cpp file, you're basically promising the compiler it's going to find in some other translation unit.

But, every const variable has a dark secret - it's trapped inside its defining translation unit because it is implicitly given static linkage. You promised your compiler whatever will be shared across multiple translation units, but it is actually loyal to just one translation unit and doesn't like to be shared. And, well, you know the rest.

Resolve by explicitly stating extern in the implementation file.



回答2:

3.5/3

 A name having namespace scope (3.3.5) has internal linkage if it is the name of
 ...
 — an object or reference that is explicitly declared const and neither explicitly declared extern nor previously declared to have external linkage;
 ...

Vars like

 const int x = 10;

are defined implicitly as 'static'.

To make them non-static (thus non-internal), use the 'extern' modifier in ".c" file.

Try using

extern const unsigned char whatever[123] = { /* ... */ };


回答3:

const has static (internal) linkage by default in c++, use extern const in your .c file as well.
This is a random SO thread that has more info. Or google "linkage in c++".



回答4:

in C++, the const is a compiling-time const, for example,

const int cc = 100;
int a[cc];

we can use const to define the array in C++, but can't in C. Since it is const, which value can't be changed, it doesn't require to share them between multiple files. So, to say, const has internal linkage.



回答5:

To fix this, a.cpp should do:

#include "a.h"

before the definition of whatever.

If there is no previous declaration in scope then const unsigned char whatever[123] = {...}; would have internal linkage. But if a.h is included, then the definition matches the previous declaration. The header defines whatever with external linkage, and the definition matches the name.

As mentioned by others you could also put extern in the definition, so that this error doesn't occur if you forget to #include "a.h". But it is still best practice to include the headers that declare anything we're trying to define publicly.