2

We have a piece of C-code in our system which contains a few arrays like this with global access:

source.h

extern const int magic[5];

source.c:

const int magic[] = { 1, 2, 3, 4, 5};

Somebody decided it would be a good idea to change this to C++ and so the above ended up in an extern "C" block:

source.h:

extern "C" { 
    const int magic[5]; 
}

source.cc:

extern "C" {
    const int magic[] = { 1, 2, 3, 4, 5};
}

This compiled without a squeak with gcc -Wall

It wasn't until someone tried to use that array that we discovered the problem. using const inside an extern "C" causes no external symbol to be generated at all. This happens with gcc, sun workshop and ibm's compiler.

I'm somewhat at a loss as to whether or not this is expected behaviour, given that gcc doesn't warn you that you're doing something odd.

So is this behaviour for this specified by the standard, or is it a rather pervasive bug?

Tom Tanner
  • 9,244
  • 3
  • 33
  • 61

1 Answers1

8

const variables have internal linkage (as if declared static) unless you use extern to specify external linkage. You'll need external linkage if you want to define it in one source file and access it from others.

That's in addition to using extern "C" to specify the language linkage.

extern "C" { 
    extern const int magic[5]; 
}

Your C declaration correctly specified external linkage; but you removed it when you changed to C++.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • And yes, this behavior is specified in the standard. One place where it gets used in C++: http://stackoverflow.com/a/12043198/365496 – bames53 Oct 27 '14 at 17:07
  • To be fair nothing was "removed" in the source file; only in the header did `extern` vanish. – Lightness Races in Orbit Oct 27 '14 at 17:30
  • @LightnessRacesinOrbit: Indeed. But that was enough to break the linkage. – Mike Seymour Oct 27 '14 at 17:33
  • I agree with your assessment, just not the implication in your final paragraph :P – Lightness Races in Orbit Oct 27 '14 at 17:44
  • @LightnessRacesinOrbit: I don't follow. The `extern` was (correctly) present in the C declaration but (incorrectly) missing from the C++ declaration. It was removed when it was changed to C++, as I said. – Mike Seymour Oct 27 '14 at 17:55
  • @MikeSeymour: Oh, yeah, I suppose. I was talking about the definition but I guess that doesn't matter if your translation unit is now referencing a different, undefined, internally-linked array thanks to shenanigans in the header. Carry on. – Lightness Races in Orbit Oct 27 '14 at 18:02