1

From https://www.quora.com/What-are-the-types-of-linkages-in-C-programming

External linkage, means that the variable could be defined somewhere else outside the file you are working on, which means you can define it inside any other translation unit rather your current one (you will have to use the keyword extern when defining it in the other source code).

Internal linkage, means that the variable must be defined in your translation unit scope, which means it should either be defined in any of the included libraries, or in the same file scope.

None linkage, points to the default functions and braces scopes, such as defining an auto variable inside a function, this will make the variable only accessable within that function's scope.

Note that:

Any global object is externally linked by default, you can disable that by using the keyword static.

Any constant global object is internally linked by default, you can disable that by using the keyword extern.

Suppose a global variable is defined in file1 and I want to use it in file2.

  1. In file1, shall the global variable be defined with keyword extern?

    The quote above seem to contradict itself:

    • "you will have to use the keyword extern when defining it in the other source code" seems to say it should.

    • "Any global object is externally linked by default" seems to say that it doesn't need to.

  2. In file2, shall I declare global variable with keyword extern?

ad absurdum
  • 19,498
  • 5
  • 37
  • 60
Tim
  • 1
  • 141
  • 372
  • 590
  • i don't think it's mandatory in neither case. the first sentence might just happen to be wrong. let me check std – Jason Hu Oct 26 '16 at 01:55
  • One is external linkage, one is externally linked. I think there is a different. – Danh Oct 26 '16 at 02:01
  • 1
    That statement that you need to use `extern` where the variable is defined is incorrect. You only need to use `extern` in the file where you're referencing a variable that is defined elsewhere. – Andy Schweig Oct 26 '16 at 02:05
  • @AndySchweig I beg to disagree. You need `extern` in the same unit where the variable is defined if it is defined with an internal linkage. – Dima Chubarov Oct 26 '16 at 02:49
  • @DmitriChubarov your comment makes no sense; a variable cannot be defined with internal linkage and have `extern` – M.M Oct 26 '16 at 02:58

3 Answers3

3

tldr: You should declare the variable, with extern, in a header file which is included by both file1 and file2. You should then define the variable in file1 only. To define the variable, you declare it without extern (and also without static).


You sound like you have gotten the extern keyword and the standardese term "external linkage" mixed up.

A variable with "external linkage" is accessible from any function in the program, as long as a declaration of the variable is visible to that function. In contrast, a variable with "internal linkage" is accessible from, at most, one "translation unit" (a single source file and all the files it includes), and a variable with "no linkage" is only visible within a single function. (I don't remember off the top of my head whether a static variable declared within a function is considered to have internal linkage or no linkage.)

The extern keyword, applied to a variable declaration, has two effects. First, it guarantees that that variable will be given external linkage, even if the declaration is inside a function (don't do that). Second, and much more importantly, it makes the declaration not be a definition. What that means is, if you have these two files

/* file1.c */
extern int foo;

/* file2.c */
extern int foo;
int main(void) { return foo; }

their combination is not a valid program. You will get an error from the linker, probably reading something like "undefined reference to foo".

To make this a valid program, you must remove the extern from one of the two declarations of foo. That declaration then becomes a definition, and the program will link. (Also, that declaration can then be given an initializer, if you want it to have a value other than 0 at startup.)

If you remove the extern from both of the definitions of foo, the result is, IIRC, implementation-defined. Some C compilers will merge them into a single global variable, and others will issue a link-time error. Sometimes the behavior depends on whether or not the variables have initializers.

It is OK to write

/* file1.c */
extern int foo;

/* file2.c */
extern int foo;
int foo;

This allows you to put the extern declaration in a header file that both .c files include, which reduces the risk of the declarations coming to have inconsistent types (if this happens, the program will exhibit undefined behavior).

zwol
  • 135,547
  • 38
  • 252
  • 361
1

c11 draft, 6.2.2, 4th section, states:

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

i don't think there will be any difference with or without extern keyword. some experiment also indicates that:

following 2 compiled:

extern int a;
extern int a;

int a = 20;

and

extern int a;
int a;

int a = 20;

but not this one:

extern int a;
int a = 10;

int a = 20;

however, i have some impression that once i read about the different behavior when dynamic linkage get involved in windows. I cannot find it though. it would be nice if anyone can confirm.

Jason Hu
  • 6,239
  • 1
  • 20
  • 41
1

The text you quoted has a lot of errors. I would recommend not relying on information from that site.

(you will have to use the keyword extern when defining it in the other source code).

Not true, as file-scope definitions have external linkage unless the static keyword is used (or no specifier is used and they are re-declaring something already declared with the static keyword).

It is possible to include a redundant extern in the definition, however there must also be an initializer (otherwise it would be a declaration and not a definition).

Internal linkage, means that the variable must be defined in your translation unit scope, which means it should either be defined in any of the included libraries, or in the same file scope.

Presumably this means "included headers", not "included libraries".

Any constant global object is internally linked by default, you can disable that by using the keyword extern.

This is wrong, "global objects" have external linkage unless declared with static. The author might be mixing up C with C++ (in the latter, const global objects have internal linkage unless otherwise specified).


Suppose a global variable is defined in file1 and I want to use it in file2.

// file1.h (or any other header)
extern object_t obj;

// file1.c
#include "file1.h"
object_t obj;   // or: extern object_t obj = { 1, 2, 3 };

// file2.c
#include "file1.h"
M.M
  • 138,810
  • 21
  • 208
  • 365