Skip to content

Instantly share code, notes, and snippets.

@kfish
Last active June 11, 2024 22:34
Show Gist options
  • Save kfish/a696f7496bdbe6810d51bdf4199cc64d to your computer and use it in GitHub Desktop.
Save kfish/a696f7496bdbe6810d51bdf4199cc64d to your computer and use it in GitHub Desktop.
C++ Visibility and Linkage of static, inline and extern

Visibility and Linkage of static, inline, and extern

static inline

// foo.h
static inline bool use_foo = true;
  • static: Limits the variable's linkage to the current translation unit. Each translation unit (source file including this header) will have its own separate instance of use_foo.
  • inline: In the context of variables, this ensures the definition can be included in multiple translation units without causing multiple definition errors.

In this case, each translation unit will have its own instance of use_foo. This is not the same instance when referenced in multiple translation units.

extern

To have a single instance of the variable across translation units, you would use extern:

// foo.h
extern bool use_foo;
// foo.cpp
#include "foo.h"
bool use_foo = true;
  • extern: Declares the variable without defining it, indicating that the variable is defined elsewhere (in one translation unit).

In this case, all translation units will reference the same instance of use_foo.

Comparison

  • static inline:

    • Visibility: Limited to the translation unit.
    • Instance: Each translation unit has its own instance.
  • extern:

    • Visibility: Across all translation units that include the header.
    • Instance: All translation units reference the same instance.

Historical Evolution

C77 (K&R C)

  • static: Used for file-scope (translation unit) variables and functions.
  • extern: Used to declare variables defined in other translation units.

C89 (ANSI C)

  • Standardized the use of static and extern.
  • Introduced the concept of translation units and linkage.

C99

  • Introduced inline functions, allowing function definitions in headers.

C++98

  • Inherited static and extern from C.
  • Introduced the concept of linkage for variables and functions.
  • inline functions allowed in headers, but inline variables were not standardized until later.

C++11

  • Introduced constexpr for constant expressions evaluated at compile time, but this didn’t affect linkage directly.

C++17

  • Introduced inline variables:

    • inline variables can be defined in headers and included in multiple translation units without causing multiple definition errors.
    • These are a single instance across the entire program.
    // foo.h
    inline bool use_foo = true;
    • This would ensure use_foo is the same instance across all translation units.

C++20

  • Added more constexpr and consteval features but no direct changes to linkage and visibility.

C++23

  • Continued refinement of constexpr and consteval, further enhancing compile-time computations but not directly impacting linkage rules.

Example with C++17 inline Variable

// foo.h
inline bool use_foo = true;
  • Visibility: Across all translation units that include the header.
  • Instance: Single instance across all translation units.

Summary

  • static inline: Separate instance per translation unit, limited visibility.
  • extern: Shared instance, visible across translation units.
  • inline (C++17 onwards): Single instance across translation units, similar to extern but can be defined in headers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment