What is external linkage and internal linkage?
When you write an implementation file (.cpp
, .cxx
, etc) your compiler generates a translation unit. This is the source file from your implementation plus all the headers you #include
d in it.
Internal linkage refers to everything only in scope of a translation unit.
External linkage refers to things that exist beyond a particular translation unit. In other words, accessible through the whole program, which is the combination of all translation units (or object files).
External, internal and no linkage or why this does not work?
§6.2.2, 7 says:
If, within a translation unit, the same identifier appears with both
internal and external linkage, the behavior is undefined.
So, your program has undefined behaviour.
§6.2.2, 4 says that
extern int a; //a_External
has external linkage because the prior declaration visible in the scope int a; //a_Local
has no linkage. But
static int a; //a_Internal
declares a
with internal linkage. Hence, it's undefined per §6.2.2, 7.
Example of showing internal vs external linkage
You need to have declarations of both variables in scope.c
.
Try adding extern int external, internal;
in scope.c
before the definition of main
. This will fix the compiler errors you're undoubtedly seeing for both variables. But you will still get a linker error for internal
only. If you comment out the line that prints internal
, but leave the line that prints external
alone, the program will compile, link and run.
How does external / internal identifier relate to the linkage?
C17 uses the term "external identifier" in these places (exhaustive list):
Paragraph 5.2.4.1/1 requiring that a conforming implementation be able to translate and execute at least one program containing at least 31 significant initial characters in an external identifier.
Footnote 72 to paragraph 6.4.2.1/3, discussing the semantics and handling of extended characters in identifiers on systems whose linkers cannot accept extended characters. On such systems, "Extended characters may produce a long external identifier."
Paragraph 7.16.1/1, about potential name collisions with the
va_*
variadic-argument access macros / functions.Paragraph 7.17.1/6, about potential name collisions with the generic functions declared in stdatomic.h.
Paragraph J.1/1, referring back to section 5.2.4.1
Paragraph J.2/1, referring to undefined behavior described in section 7.13 in the event that "the program defines an external identifier with the name
setjmp
."Paragraph J.2/1, referring to section 7.16
All of those are about linkage -- that is, the association of identifiers with the objects or functions -- not about (say) the lexical context of the identifier's declaration.
Furthermore, although the specification does not explicitly define "external identifier", it does, in paragraph 6.4.2.1/5, define "external name" as "identifier that has external linkage". It also uses the word "name" as a synonym for "identifier" in several places, generally in the context of function names.
I have every reason, then, to take "external identifier" to be synonymous with "external name" and "identifier with external linkage". The main alternative would seem to be "identifier declared in an external declaration", but it makes little sense that some of the particular provisions related to external identifiers should apply only to identifiers appearing in external declarations and not to identifiers declared at block scope with external linkage.
The term "internal identifier" appears only once in C17, in paragraph 5.2.4.1/1, requiring that a conforming implementation be able to translate and execute at least one program containing at least 63 significant initial characters in an internal identifier. This is parallel to one of the appearances of "external identifier", and, also parallel to "external identifier", there is a definition the related term "internal name": "a macro name or an identifier that does not have external linkage" (paragraph 6.4.2.1/5).
Similarly to the case with "external identifier", then, I take "internal identifier" to be synonymous with "internal name": an identifier that does not have external linkage. Another way to say that would be an identifier with internal linkage or no linkage.
inline definition of function - external or internal linkage
Your example actually violates the one definition rule. In short, with an inline
function you're allowed to have multiple definitions provided that each one:
- is in a different translation unit (which you do have)
- each definition has the same sequence of tokens (which you clearly do not)
So this is actually UB.
inline
functions require there to be a definition in every translation unit where they are ODR used, so they can be completely defined in a header without a compilation unit for example.
This is not the same as "inlining" a function. inline
only implies that the function is defined "in-line" with it's declaration. Any function will or will not be inlined at the discretion of your compiler.
external vs internal linkage and performance
No, all three have external linkage. Member functions of a non-local class always have external linkage in C++. Moreover, inline
has no effect on linkage, even if it is a non-member function.
Linkage has no effect on efficiency. Inlining might have, but it depends on too many variables.
Related Topics
Checking the Neighbour Values of Arrays
Infinite Loop With Cin When Typing String While a Number Is Expected
Pass by Reference/Value in C++
Why Can't the Switch Statement Be Applied on Strings
Why Do I Get the Same Sequence For Every Run With Std::Random_Device With Mingw Gcc4.8.1
Where Are Static Variables Stored in C and C++
If You Shouldn't Throw Exceptions in a Destructor, How to Handle Errors in It
What Is External Linkage and Internal Linkage
Case-Insensitive String Comparison in C++
How to Print a Variable'S Type in Standard C++
Implicit Type Conversion Rules in C++ Operators
Overloading Friend Operator≪≪ For Template Class
C/C++ Maximum Stack Size of Program on Mainstream Oses
Running My C++ Code Gives Me a Blank Console
How to Call a Constructor from Another Constructor (Do Constructor Chaining) in C++
Print Heart Shape With Words Inside
When Should I Write the Keyword 'Inline' For a Function/Method