Sign in to follow this  
Markie

(VS)C++ Namespaces: Internal or External Linkage?

Recommended Posts

Hi all,

I'm trying to come to exact grips with C++ namespaces and have a question which is not answered exactly by my C++ books:

Do variables declared inside a namespace have INTERNAL or EXTERNAL linkage?

The reason why this question comes up is this:
One of my C++ books (by Stephen Prata) states, quote:
Quote:
Namespaces can be located at the global level or inside other namespaces, but they cannot be placed in a block. Thus, a name declared in a namespace has external linkage by default (unless it refers to a constant).


I think this is total bull****!
When testing with Microsoft Visual Studio 2005 it seems to be the opposite!
While names declared inside a namespace certainly have Static Storage Duration, they do not have EXTERNAL linkage, but INTERNAL linkage!

Here's what MS Visual Studio 2005 does:

If you create two source code files in one C++ project, but NO HEADER FILE, and then place this code in the first file "SourceCodeFile_1.cpp":

namespace TestNamespace
{
int myTestVariable = 5;
}






and this code in the second file "SourceCodeFile_2.cpp":

using namespace TestNamespace;

// Now try using myTestVariable:
if (myTestVariable != 0)
{
...
}






Microsoft Visual Studio 2005 will complain:
Quote:
SourceCodeFile_2.cpp : error C2871 : 'TestNamespace' a namespace with this name does not exist
SourceCodeFile_2.cpp : error C2065 : 'myTestVariable' : undeclared identifier


Now, if namespaces would truly be like EXTERNAL variables with static duration, - which require:
- A Defining Declaration in one source code file and
- A Referencing Declaration (using the keyword 'extern') in the other source code file that wants to use it, this would work. But it doesn't!
The only way to use variables declared inside a namespace is to put the namespace in a header file and then include that header file in each source code that wants to use said variables.
But that's the exact behavior of variables with Static Duration and INTERNAL LINKAGE!

Or is this actually Microsoft Visual Studio that does (STILL?) not implement the C++ standard correctly?

What's weird is that both my big C++ bibles state that "Unnamed Namespaces" mimic the behavior of Static Duration variables with INTERNAL linkage, as if that were anything special, as if "normal" (= named) namespaces would mimic the behavior of variables with EXTERNAL linkage, which, as we saw in my test with MS Visual Studio 2005, is NOT the case!

Who's right?
My C++ books, MS Visual Studio or me?
Do Names declared in namespaces behave like Static Duration variables with EXTERNAL LINKAGE (can be shared among multiple source code files of one project WITHOUT any header files!) or like Static Duration variables with INTERNAL LINKAGE (can be shared with multiple source code files ONLY via a header file that must be included by all variable-using source code files)?

Any help by "C++ gods" appreciated!!
:-/

Greetings,
Mark

Share this post


Link to post
Share on other sites
What you are trying is not internal vs. external linkage. You're simply using a namespace and a variable that hasn't been declared in the translation unit. You need a header file that defines the namespace and declares the variable as extern:

namespace TestNamespace
{
extern int myTestVariable;
}

Then you can include this header anywhere, and you will see that the variable has external linkage because you can access it from any other translation unit.

To make the variable have internal linkage, either define it as static, or within an anonymous namespace (use either of the definitions below).

static int myTestVariable = 5;

namespace
{
int myTestVariable = 5;
}


You can try the internal vs. external linkage in other ways also. If it has internal linkage, you should be able to define the same symbol in multiple translation units without linking problems. So, if you put the following in multiple translation units:

namespace TestNamespace
{
int myTestVariable=5;
}

you'll get multiple definition link errors, because there are multiple TestNamespace::myTestVatiable defines with external linkage.

The book and your compiler are both right. But your compiler is not evaluating linkage, but just complaining about missing declarations.

Share this post


Link to post
Share on other sites
Quote:
Original post by Brother Bob
What you are trying is not internal vs. external linkage. You're simply using a namespace and a variable that hasn't been declared in the translation unit. You need a header file that defines the namespace and declares the variable as extern:

namespace TestNamespace
{
extern int myTestVariable;
}

Then you can include this header anywhere, and you will see that the variable has external linkage because you can access it from any other translation unit.

Actually I think 'extern' is not necessary as it's the default for namespaces, isn't it?
But anyway: Wait, just a minute here:
If I *need* a header file, that behavior can't be described as "Static Duration with External Linkage". No?
The whole point of Static Duration with External Linkage (a.k.a. "globals") is that a variable declared in one source code file (with a Defining Declaration) can be used in other source code files (after a Referencing Declaration) WITHOUT ANY HEADER FILES AT ALL(!!). No??? This is true "multi-file" scope, "External Linkage", no?

I can put anything in a header file. But when I need to include a header file, I'm actually pasting the entire header file into every source code file.

Oh wait...
I get it:
Variables in namespaces behave like variables with internal linkage in that they must be included via header file in EVERY source code file, BUT they behave like variables with EXTERNAL linkage in that, if doing so (including the declaration of the namespace containing the variable declaration via header file into every source code file), and the variable becomes available (in scope) in the source code files, it behaves like an EXTERNAL linkage variable in that there is only ONE copy!!! :-)
If any source code changes the value of the variable, it changes the value of the variable for all other source codes as well, because it's really only ONE variable.
With 'true' INTERNAL linkage, if a variable is placed in a header file with the keyword 'static', it generates multiple copies, one in every header-file including source code, with identical names.

Hmm...

So INTERNAL and EXTERNAL linkage refers not so much as to how to share things across multiple source code files (by using a header or not, that's not the relevant point), but rather IF there is ONE single copy for ALL source code files or multiple SEPARATE copies (one for) each, right?

That would explain a lot!!
:-)

Thanks!!!
:-)

Mark

Share this post


Link to post
Share on other sites
You are confused about what linkage refers to. A symbol has to be declared in order to be able to use it. Your first code didn't define neither the namespace nor the variable in that translation unit, so you got compilation errors about undeclared symbols. That has nothing at all to do with external or internal linkage. It's simply a lack of declaration.

Once I showed you the header file that you include, the symbols are defined and you can use them. Whether it is exposed from the other source file or not, and thus whether you can access it from other translation units, is where internal or external linkage comes into play. If it has internal linkage, you cannot access it from other translation units. If it has external linkage, you can.

But, as I said, the symbol first needs to be defined in order to be able to use it at all. Then linkage dictates whether it is exposed from the translation unit or not.

Share this post


Link to post
Share on other sites
Quote:
Original post by Brother Bob
You are confused about what linkage refers to.

Yep, thanks. That's correct, I think I was, my quote:
"Actually I think 'extern' is not necessary as it's the default for namespaces, isn't it?"
This was my problem I think. Reading that "a name declared in a namespace has external linkage by default", and thinking that namespaces were somehow supposed to make life easier regarding the use of Referencing and Defining Declarations of global variables and the use of static variables, I thought that variables inside namespaces no longer needed a Referencing Declaration using the keyword 'extern'.
That's why I falsely thought the keyword 'extern' is being added automatically as a default to all variables inside namespaces.
I guess I simply misunderstood that sentence in that book, "a name declared in a namespace has external linkage by default". I thought it meant the keyword 'extern' was added automatically somehow and that referencing declarations were not necessary inside namespaces. WRONG!!!
:-)

I did some more testing now and you're right:
Variables inside namespaces behave exactly like variables with Static Duration outside namespaces. They can have either EXTERNAL Linkage, in which case they need ONE Defining Declaration and a Referencing Declaration in ALL source code files that use them, using the keyword 'extern', or STATIC Linkage, using the keyword 'static', in which case they are only visible (or create a new variable with the same name) in the file they are defined in (or in the source code files that include a header with their static definition.

Stating that "a name declared in a namespace has external linkage by default" was just irritating, because that seemed to imply somehow, that names declared inside namespaces somehow do not behave as those declared outside namespaces.
BOTH have external linkage by default. It's simply omitting any keyword, either 'static' or 'external' which gives a variable outside of any code block external linkage, which in turn requires a Referencing Declaration by all other files who want to use it, or, if they want to use an own, local variable with the same name ('overwriting' its scope), the declaration of a static variable with the keyword 'static'. This all is the SAME, both for variables inside namespaces as well as variables outside namespaces!
:-)

Now I think I got it...
:-)

THANKS A LOT! :-))))
Mark

Share this post


Link to post
Share on other sites
Quote:
Original post by Brother Bob
To make the variable have internal linkage, either define it as static, or within an anonymous namespace (use either of the definitions below).

Symbols defined within an anonymous namespace have external linkage, not internal linkage. The names, however, are mangled such that symbols inside anonymous namespaces have unique identities in translation units. The difference becomes important when dealing with some template code which requires symbols with external linkage, in which case you can use symbols from anonymous namespaces but can't use variables with true internal linkage such as those defined with static. Also, static isn't the only way to make a variable have internal linkage. A const variable at namespace scope also has internal linkage unless also declared with extern; this is why you can put const variables in headers without getting multiple symbol linker errors. Data members of anonymous unions also have internal linkage.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Quote:
Original post by Brother Bob
To make the variable have internal linkage, either define it as static, or within an anonymous namespace (use either of the definitions below).

Symbols defined within an anonymous namespace have external linkage, not internal linkage. The names, however, are mangled such that symbols inside anonymous namespaces have unique identities in translation units. The difference becomes important when dealing with some template code which requires symbols with external linkage, in which case you can use symbols from anonymous namespaces but can't use variables with true internal linkage such as those defined with static. Also, static isn't the only way to make a variable have internal linkage. A const variable at namespace scope also has internal linkage unless also declared with extern; this is why you can put const variables in headers without getting multiple symbol linker errors. Data members of anonymous unions also have internal linkage.

I was not aware of that subtle difference for anonymous namespaces. On a more advanced level, as your template example, I see why that can make an important difference.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this