Internal and external linkage

Decide whether a global name stays within one translation unit or is shared across files.

The gist

Linkage Where the identifier can be used Same name in another file
Internal Only within its own translation unit Refers to an independent entity
External From other translation units via a declaration Refers to the same shared entity

Defaults at a glance

Identifier at global scope Default linkage Make it internal Make it external
Non-constant variable External static or unnamed namespace Nothing—already external
const variable Internal Nothing—already internal extern on its initialized definition
constexpr variable Internal Nothing—already internal Possible with extern, but rarely useful
Function External static or unnamed namespace Nothing—already external

Internal linkage

Use internal linkage for globals, helper functions, and types that are implementation details of one translation unit:

namespace
{
	int g_count {};

	int add(int x, int y)
	{
		return x + y;
	}
}

const int maxItems { 10 };   // internal by default
constexpr int retries { 3 }; // internal by default

An unnamed namespace works for many kinds of identifiers and is convenient when several names should be internal. static is another option for a global variable or function:

static int g_count {};
static int add(int x, int y);

Two files may define internal identifiers with the same name. They are separate entities, so this does not violate the one-definition rule.

External linkage

Use external linkage when multiple translation units must use the same entity. Put declarations in a header and one definition in a source file:

// globals.h — declarations
extern int g_count;
extern const int maxItems;
void sayHi();
// globals.cpp — the one set of definitions
int g_count {};
extern const int maxItems { 10 };

void sayHi()
{
	// ...
}

Other source files include the header. The compiler sees the declarations, and the linker connects each use to the definitions.

External non-constant globals and functions are external by default. Avoid writing extern on their definitions; reserve it for variable declarations and definitions of external const globals.

Choosing quickly

  • Used only in this translation unit? Give it internal linkage.
  • Used by multiple translation units? Give it external linkage, declare it in a header, and define it once in a source file.
  • Internal definitions with the same name in different files are independent.
  • An ordinary external object or function must have only one definition in the program.