18

Please refer to the following code that is in the same translation unit:

static int global_var; // file scope in C and global namespace scope in C++
                       // internal linkage
void f(void)
{
    static int local_var; // block scope in C and local scope in C++
                          // no linkage 
}

My understanding is this:

  • I can refer to global_var from anywhere in the translation unit because it has global scope.
  • I can refer to local_var only inside function f because it has local scope.

My questions:

  1. What is the difference beteen the two variables, in relation to linkage?
  2. Can you provide one example where internal and no linkage makes a difference, and the difference is derived not only from scope?

EDIT

After the answer and comments of James Kanze, I am now able to construct an example that shows the difference between the internal and no linkage attributes:

static int i; // definition
              // static storage
              // internal linkage

void f(void)
{
    extern int i; // declaration
                  // refers to the static i at file scope
                  // note that even though the specifier is extern
                  // its linkage is intern (this is legal in both C/C++)
    {
        int i; // definition
               // automatic storage
               // no linkage
    }
}


Some articles that do a good job at explaining the concepts involved:
- Scope regions in C and C++
- Storage class specifiers and storage duration
- Linkage in C and C++

zephon
  • 310
  • 2
  • 8
  • Internal linkage refers to everything only in scope of a translation unit – Rahul Tripathi Jul 21 '14 at 12:15
  • Looks like homework, right? – NirMH Jul 21 '14 at 12:17
  • @NirMH Actualy I would be very interested of where this type of homeworks are asked. The answer is no, this is not my homework. I asked this question to clarify my understanding of linkage and scope in C++. – zephon Jul 21 '14 at 12:34
  • Local scope implies no linkage, namespace scope can be either internal or external, class scope (at least in a non-local class) is always external. – James Kanze Jul 21 '14 at 13:17
  • @JamesKanze since c++11 there is no `Local scope`, only `block scope`. standard wording: `a name declared at block scope (6.3.3) has no linkage` – Chen Li Dec 02 '17 at 04:09

3 Answers3

14

First: in addition to type, variables have three other characteristics: linkage, scope and lifetime. All four attributes are sort of orthogonal, but linked in the way they are expressed in the language, and do interact in some ways.

With regards to linkage: linkage really affects the symbol which is being declared, and not the object itself. If there is no linkage, all declarations of the symbol bind to different objects, e.g.:

int
func()
{
    int i;
    {
        int i;
    }
}

The symbol i has no linkage, and the two symbols i are bound to two different entities. Generally speaking, local variables (variables declared at block scope) and function arguments have no linkage, regardless of type and lifetime.

Internal and external linkage are similar, in that repeated declarations of the symbol bind to the same entity: internal linkage binds only within the translation unit, external accross the entire program. So given:

static int i;   //  internal linkage...

in several translation units, the i binds to a separate entity in each translation unit. Without the static, you have external linkage, and all of the i bind to the same entity.

Note that this only holds at namespace scope; all entities which are members of a non-local class have external linkage.

And that type has an impact: variables which are const implicitly have internal linkage:

int const i = 42;    //  same as static int const i...
extern int const j = 42;    //  external linkage.

Finally, all declarations which bind to the same entity must declare it to have the same type. If you violate this rule in a single translation unit (e.g.:

extern int i;
//   ...
double i;

in the same namespace scope), then the compiler should complain. If the two declarations are in different translation units, however, it is undefined behavior, and who knows what will happen. (In theory, the linker could complain, but most don't.)

EDIT:

One additional point: linkage is determined by the first declaration which can refer to the entity. So if I write:

static int i;

void
func()
{
    extern int i;
}

Both i refer to the same entity, which has internal linkage. (Why one would ever write the second declaration is beyond me, but it is legal.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • @GradyPlayer sorry I did not asked the question that you wanted me to ask. I am not asking a general question about linkage, I am asking specificaly about **internal** and **no linkage** i.e. same translation unit. – zephon Jul 21 '14 at 13:36
  • @zephon, it is just semantics, what symbols go where in the object so they can be accessed... if that really is the question that you want answered it will have a different answer for a different ABI, and you can inspect the ASM output of a compiler to see what they are doing... it also has a semantic difference dealing with optimizations - but not a big one, because it only has to resolve the symbol within the one compilation unit before it can discard it if it isn't used. – Grady Player Jul 21 '14 at 13:40
  • @zephon I realized that later; you do seem to understand many of the differences. If you read carefully, you'll find that I did answer the question you asked, among many other things. Look at the first example and the very last one (after my edit). – James Kanze Jul 21 '14 at 14:05
  • 1
    You are sugesting that the two *i* sybols bind to different entities because they have internal linkage. Please refer to Example 2 of my post. Why is the second *i* a different entity? – zephon Jul 21 '14 at 14:06
  • @zephon Because the second `i` has _no_ linkage. The language is not always orthogonal with regards to how linkage is determined; a variable declaration at block scope has no linkage unless it is declared `extern`, in which case it has external linkage _if_ there is no preceding declaration at namespace scope, or the linkage of the preceding declaration if there is one. It's what I tried to say in my first paragraph: the four characteristics are sort of orthogonal, except that they do sometimes interact. – James Kanze Jul 21 '14 at 14:10
  • @GradyPlayer My intention is to understand the semantics of internal linkage(vs no linkage) from a C/C++ programmers point of view. But if I can get a different results for a different ABI, doesn't that mean that it is not defined? – zephon Jul 21 '14 at 14:27
  • @JamesKanze I believe the reason why in my example the two *i* s are different, is because the second declaration is also a definition which shadows the first *i* definition. In your example the second declaration is not a defintion. You are right, the language lets you do such things as changing a declaration specifier from static to extern, but not the other way: first declaring extern, than static is undefined. – zephon Jul 21 '14 at 14:39
  • @zephon It's linked. If two declarations bind to the same entity, only one can be a definition. In your second example, one could just as easily say that the second declaration of `i` is a definition _because_ it has no linkage to attach it to the first declaration/definition. How linkage works is fairly orthogonal to the other attributes, but how a declaration determines linkage is a complicated mix of things; the standard takes three pages to describe it. In block scope, function declarations and names declared with `extern` have linkage, other names don't. – James Kanze Jul 21 '14 at 14:54
  • @JamesKanze [This](http://www.embedded.com/design/prototyping-and-development/4007522/Linkage-in-C-and-C-) article explains very well some of the important details of linkage. If we talk about C++, then it very well explains that *extern int i;* is a non-defining declaration and *static int i;* is a declaration. In your example, there is one definition and one non-defining declaration => one entity and in mine there are two definitions => two entites. – zephon Jul 21 '14 at 15:17
  • My conclusion is that **variable shadowing** is possible because of the **no linkage** property. If my conclusion is correct than your answer is complete. – zephon Jul 22 '14 at 07:28
  • @zephon Formally: shadowing is concerned with scope, not linkage (and it's possible to shadow with linkage, e.g. `extern in i;` in an inner block will shadow an `i` defined in an outer block, and be shadowed by an `i` in a nested block). Practically, of course, at most one declaration with linkage can be involved in shadowing, and you have to jump through hoops to get it involved; the no linkage property is certainly necessary for some of the declarations involved. – James Kanze Jul 22 '14 at 09:25
  • @JamesKanze Refering to your example, when *extern int i;* is encountered, this is a declaration with external linkage. At the next *int i;* in an inner block, this will be a declaration (and a definition), with no linkage. If it would have internal linkage then it would conflict with a previous definition, because two definitions are found. That is how I explain to myself the difference between internal and no linkage. – zephon Jul 22 '14 at 10:27
  • @zephon Yes, but `extern int i;` can shadow `int i;`. That's my only point: shadowing is an effect of and on scope, not on linkage. – James Kanze Jul 22 '14 at 13:15
  • @JamesKanze I agree on your point, shadowing is an effect of and on scope. My addition to this, is that it is made possible by the existance of the no linkage attribute (at least in this example). – zephon Jul 22 '14 at 14:29
  • @zephon Generally, yes. (A local declaration `extern int i;` can hide a member variable `i`, but I'm not sure hiding member variables would be called shadowing.) – James Kanze Jul 22 '14 at 15:11
  • @JamesKanze Is there is a formal definition of variable shadowing? I see it more as a result/consequence of certain combinations of linkage and scope attributes. – zephon Jul 22 '14 at 15:25
  • @zephon I don't know. The standard uses the terms _potential scope_ and _scope_; the potential scope is the scope the symbol would have if there wasn't a declaration inside that scope. So if I have something like: `struct C { int b; void f() { extern int b; } };`, if we consider shadowing to be the potential scope minus the scope, `extern int b;` shadows `C::b` in `C::f()`. – James Kanze Jul 22 '14 at 16:44
  • @JamesKanze Thank you for your clarifications. I have edited my answer to add an example that shows the difference that I am interested in. – zephon Jul 22 '14 at 17:30
0

Generally static variables have internal linkage. You can't access the static variable or function in another file(in multiple file compilation situations), because its scope limited within this file(Internal linkage). Normally auto and register variables have no linkage.


As i said above auto and register variables have no linkage. You can't declare these variables in global scope. static variables has internal linkage, scope is based on declaration, but not possible to access in another file. extern variables has external linkage, its possible to access these variables in another file.

For more reference Storage classes

Sathish
  • 3,740
  • 1
  • 17
  • 28
  • 1
    No, `local_var` has no linkage, since it's declared at block scope. Storage duration has nothing to do with linkage, which is (mostly) determined by scope. – Mike Seymour Jul 21 '14 at 12:36
  • The document you link to is completely wrong (with sections like "external storage class", which doesn't exist). – James Kanze Jul 21 '14 at 13:14
0

global_var could be accessed from void g() in the same compilation unit, that is the difference.

Grady Player
  • 14,399
  • 2
  • 48
  • 76