Internal linkage property for an identifier makes it visible to a single translation unit and not accessible from other translation units. In simpler terms, same name identifiers present in different source code files are private to those source code files. It does not violet ODR.
For example, identifiers with name a can exist in main.cpp and lib.cpp. main.cpp’s a is just visible to main.cpp only, same goes for lib.cpp.
Global variables have external linkage by default. To make them internal, we can use static keyword.
Note
statickeyword is a storage class specifier which sets both internal linkage and storage duration properties of an identifier.
lib.cpp
int value{2};main.cpp
#include "../helpers/stdout.h"
static int value{1};
int main(int argc, char const *argv[])
{
print(value);
print(pi);
return 0;
}In main.cpp, identifier value is static which makes it internal to main.cpp and when it compile with lib.cpp, the compilation does not complain about duplicate identifiers as main’s value is internal.
Constant global objects have internal linkage by default. This property enables us to put them into header files without the violation of ODR.
For example, if we have a bunch of constants that we want to use in multiple cpp files, we could use a header file and include them in the cpp files as shown below. As global constants are internal, there will be error for duplication.
constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
const double pi{3.14};
constexpr double lightSpeed{3e10};
#endiflib.cpp
#include "constants.h"
// other library functionalities...main.cpp
#include "constants.h"
#include "../helpers/stdout.h"
int main(int argc, char const *argv[])
{
print(pi);
return 0;
}
Compiling this program using command,
g++-15 -ggdb -std=c++20 main.cpp lib.cpp ../helpers/stdout.cpp -o ma
in.out
should happily compile it.
If constant globals were not internal linkage by default, there would be ODR violation and causes duplication compilation error.