Reputation: 291
I am refactoring a c++ code and there is something I cannot understand. The code is declaring a set of arrays in a header file then include that header file in source files when needed. All arrays are "const unsigned char[]" except one which is "const char *[]" array. The latter is surrounded with an #ifdef SOMETHING. If SOMETHING is not defined code is built successfully, otherwise I got linker errors of multiple definitions for this "char *[]" only.
As a fix, I can eliminate those linker errors by adding "static" to "const char* XX[3] = {"X", "Y", "Z"}". This will keep the definition specific to the translation unit.
However, what I cannot understand why "multiple definitions" errors only occur with "const char* []" array and not with the others "const unsigned char[]" despite they are not preceded by a "static" keyword? Could someone explain that to me please?
Upvotes: 4
Views: 1782
Reputation: 477434
Constant variables at namespace scope implicitly have internal linkage (if you will, they are implicitly static
). The following declares and defines two distinct objects.
// A.cpp // B.cpp
const T foo = 1; const T foo = 2;
If you wanted external linkage, you'd have to say extern const T foo;
.
By contrast, non-constant variables at namespace scope have external linkage (if you will, they're implicitly declared extern
) and all denote the same object, so you are violating the one-definition rule:
// A.cpp // B.cpp
U bar = 1; U bar = 2; // ODR violation
Here, if you wanted internal linkage, you'd have to say static U bar;
.
This is your case. You have T = char []
and U = const char * []
. (Here const T
produces the type const char []
by 8.3.4/1.)
The solution is to not define your variables in headers if the variables have external linkage, since the header gets included in multiple translation units. Instead, only declare the variable in the header and define it in one single translation unit:
library.h:
extern U bar; // in your case, extern const char * XX[];
library_impl.cpp:
#include "library.h"
U bar = 3;
Upvotes: 8