5

I would like to know why you can not declare a global with the same name in 2 different .cpp files. My understanding is considering scope, that it should only be visible to that particular .cpp file and no where else but it is obviously complaining. The reason I'm doing this is for commonality in code and that's it. any ideas?

Edit for Clarity

a.cpp

int g_x;

b.cpp

int g_x;

Questioneer
  • 761
  • 4
  • 12
  • 20

6 Answers6

8

To make a global variable (or function) only visible to the file it's declared in,

  1. declare it static, or
  2. (the way that is preferred in C++) put the variable in a nameless namespace. It would seem like that would make it inaccessible from outside the namespace, but what it actually does is make it only visible to the file in which it is.

To access a global variable (that is not static or in an anonymous namespace) that is declared in some other file, use extern.

The reason why is the same reason why you can't have a function with the same name in two different files. It confuses the linker because global variables by default have external linkage. static or being in an anonymous namespace gives them internal linkage, which makes them like a "local global variable".

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • 2
    `static` is deprecated for this purpose. – John Dibling Nov 30 '11 at 17:05
  • 1
    Since the question is tagged C++, there is also the possibility to use anonymous [namespaces](http://www.cprogramming.com/tutorial/namespaces.html). Actually, the use of `static` global functions and variables is deprecated in favor of namespaces. – Some programmer dude Nov 30 '11 at 17:08
  • 4
    @JohnDibling: I believe it is un-deprecated in C++11. – Fred Larson Nov 30 '11 at 17:09
  • @JohnDibling - Is this use of `static` deprecated in both C and C++? – Robᵩ Nov 30 '11 at 17:11
  • 1
    @Rob: I can't speak to C on this matter. – John Dibling Nov 30 '11 at 17:13
  • 1
    @Fred: Can you provide a reference to this? – John Dibling Nov 30 '11 at 17:14
  • 1
    @JohnDibling: Looking. Best I have so far is this: http://stackoverflow.com/q/4726570/10077 – Fred Larson Nov 30 '11 at 17:14
  • 1
    @JohnDibling: It's more an absence of reference actually. In n3225 and in the FDIS the sentence about deprecation has been removed. Since there is no other mechanism in C, and since we generally want as much interop as we can get, deprecation did not make sense. – Matthieu M. Nov 30 '11 at 17:18
  • 1
    @JohnDibling Ok, updated with the anonymous namespace option. – Seth Carnegie Nov 30 '11 at 17:18
  • 2
    @JohnDibling: And via Fred's link, eventually we find the [relevant defect resolution](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1012). I thought Herb Sutter had mentioned this on his blog too, but I can't find it right now... – John Marshall Nov 30 '11 at 17:21
  • Static only makes one instance of it though across the files. I don't mean it is accesible by the other files though. If I declare both of them static it would complain? – Questioneer Nov 30 '11 at 17:23
  • 1
    @Questioneer: if there are two static globals in different translation units, as far as linking is concerned, it's as if they have different names. Even if they have the same types, they are two separate variables. No complaints. (But maybe you should show us an example of what you're trying to do...) – John Marshall Nov 30 '11 at 17:26
  • 1
    @Questioneer: *`static` only makes one instance of it though across the files*, that's for class variables, there are several usages with different meanings for the `static` keyword. For objects and functions globals declared in a namespace, it simply restricts the scope of the global to the current translation unit (current file if you don't use it in headers) and prevent name clashes. – Matthieu M. Nov 30 '11 at 17:49
  • I made an edit on something that is very generalized but I think shows what I'm trying to do. – Questioneer Nov 30 '11 at 18:07
  • 1
    @Questioneer yes, that will be fine and the code in each file will have its own version of `g_x` – Seth Carnegie Nov 30 '11 at 22:37
6

The Problem:
Global variables have External linkage, i.e: They are visible throughout the program.
if 2 different files have variable with same symbol name then it breaks the ODR(One Definition Rule).

The One Definition Rule (ODR), as the name suggests, requires that an object with external linkage, a non-inline function, a class, an enumeration or a template shall have exactly one definition in the program.


The Solution:
Your global variables in the files should have Internal Linkage to avoid violation of ODR. There are two ways to achieve this:

Make your global variables in file static Or
Use Anonymous/Unnamed namespace.


Good Read:
Anonymous/Unnamed namespace
Speaking Standardese: the One Definition Rule


For Standerdese Fans:
C++11 3.2 One Definition Rule [basic.def.odr]:

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type or template.

Para 3:

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is odr-used.

C++11 7.3.1.1 Unnamed namespaces [namespace.unnamed]

1/ An unnamed-namespace-definition behaves as if it were replaced by

inlineoptnamespace unique { /* empty body */ }    
using namespace unique ;      
namespace unique { namespace-body }       

where inline appears if and only if it appears in the unnamed-namespace-definition, all occurrences of unique in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the entire program.94

Note: C++03 deprecated usage of static for declaring objects in namespace scope but this deprecation was removed in C++11.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 1
    Only mutable global variables have external linkage. Unqualified global *constants* have internal (or no?) linkage. – Kerrek SB Nov 30 '11 at 17:32
  • 1
    @KerrekSB: I am not sure of that,Will be glad if you could elaborate more on that with references,citation or explanation. – Alok Save Nov 30 '11 at 18:00
  • 1
    Well, `const int a = 1;` does not have external linkage; you'd have to say `extern const int a = 1;` Not sure if it's only for integral types, but there's definitely some rule concerning global constants. – Kerrek SB Nov 30 '11 at 18:05
  • 1
    Variables in an anonymous namespace have external linkage, don't they? ISTR this made a difference when you tried to use their address as a template argument. – MSalters Nov 30 '11 at 19:59
  • 1
    @MSalters: For objects in the unnamed namespace, the linkage may be external, but the name is unique, and so from the perspective of other translation units, the name effectively has internal linkage. – Alok Save Dec 01 '11 at 03:44
  • 1
    Nevermind; 3.5/4 "An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage." – MSalters Dec 01 '11 at 09:22
3

The reason why you get linker errors is because the variables have extern linkage, and are in the same namespace (namely the global one).

And the usual and recommended remedy is to put them in separate namespaces.

You can accomplish that by using an anonymous namespace, like so:

namespace {
    int my_global_variable;
}

This namespace gets a unique name in each translation unit. Say, in one translation unit the automatic name could be “gorblegorble123”. And this works as if the compiler places the following code after it:

using namespace gorblegorble123;    // As if this is present.

And ditto in other translation unit, but with different unique names.

This is the most general technique. In particular it works with class definitions.


As mentioned in some other answers you can alternatively use static to specify internal linkage, that the variable is not visible to the linker.

This usage was deprecated for objects in namespace scope in C++98 and C++03, but the deprecation was removed in C++11.

static is a limited special cases notation that can be applied to objects and functions, but not to classes.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 2
    Actually, `static` is [no longer deprecated in C++11](http://stackoverflow.com/questions/4726570/deprecation-of-the-static-keyword-no-more). – Matthieu M. Nov 30 '11 at 17:19
2

Declare the variable static (C and C++):

static int myGlobalVariable;

or declare it in an anonymous namespace (C++ only):

namespace {
    int myGlobalVariable;
}
hmjd
  • 120,187
  • 20
  • 207
  • 252
1

why you can not declare a global with the same name in 2 different .cpp files

Because any program that has multiple definitions of a single entity is ill-formed. In your case, you have two entities named the same thing, therefore the program is ill-formed.

The preferred method (In C++03 at least) to resolve this is to use unnamed namespaces:

file1.cpp

namespace
{
  int n;
};

file2.cpp

namespace
{
  int n;
};

Placing a declaration within an unnamed namespace makes that entity visible only within that translation unit.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
1

Since the question is also tagged 'c', I'd like to add my 5 cents. In C there is no "one definition rule".

In C (C99 and before, not sure about C1x) an object with file scope and without a storage class specifier constitutes a tentative definition. (section 6.9.2).

In the subsequent Example 1 on page 144, several examples are listed, concentrating all on definitions/declarations within one file. However, an extern declaration together with a declaration without storage class specifier (i3) go together well and constitute a definition with external linkage.

This means that a second file may exist referring to that definition either using extern as well, or again without storage class specifier.

So in C, you may have two files both with tentative definitions like

int i3;

and both will refer to one variable of tupe int, and the linker will make sure the both refer to the same memory location. And even if you have int abc; and char abc in two different files, the regular linker will not produce an error; hopefully it will warn you, though.

H&S5 has some more details on how various types of linkers will handle such a situation, but using the common memory model, the above is confirmed. At least IMHO.

For further references, look here, especially the answer by Alok.

Community
  • 1
  • 1
Johan Bezem
  • 2,582
  • 1
  • 20
  • 47