본문으로 건너뛰기
Previous
Next
C++ Name Mangling Explained: Symbols, extern C,

C++ Name Mangling Explained: Symbols, extern C,

C++ Name Mangling Explained: Symbols, extern C,

이 글의 핵심

How C++ encodes function and variable names for overloading and namespaces. Essential for debugging link errors, mixing C and C++, and ABI concerns.

What is name mangling?

The compiler turns function and variable names into unique symbol names that encode types, namespaces, and parameter lists. This matters for linking and ABI compatibility.

From the linker’s perspective, each symbol in the final binary is a single string. In C, short names like func suffice. In C++, several overloads can share the name func, so the compiler encodes “name + type information” into strings like _Z... in .o symbol tables.

Below, both declarations use the identifier func in source, but the linker sees different symbols.

// Source: both named "func"
void func(int x) {}
void func(double x) {}

// Roughly on GCC/Clang (Itanium ABI); details may vary by environment.
// _Z4funci  →  "func" + (int)
// _Z4funcd  →  "func" + (double)
//
// _Z : Itanium mangling prefix
// 4func : length 4 + name func
// i, d : argument type encodings (int, double)

nm on an object file may show _Z-prefixed lines. Pipe through c++filt for human-readable demangling (func(int), func(double)).

Why it is needed

// Overloading: the compiler picks which print() at the call site
void print(int x) {}
void print(double x) {}
void print(const std::string& x) {}

// At link time each definition must have a distinct mangled name.

Namespaces, class members, and template instantiations add more “name space,” so mangling encodes extra information. That keeps A::f vs B::f and vector<int>::size vs vector<double>::size distinct.

Practical examples

Example 1: Inspect symbols

# Compile
g++ -c program.cpp

# Symbols
nm program.o

# Demangle
nm program.o | c++filt

Example 2: extern “C”

// C++ mangling
void func(int x) {}
// symbol: _Z4funci

// C linkage (no C++ mangling)
extern "C" void func(int x) {}
// symbol: func

// C library headers
extern "C" {
    #include <stdio.h>
}

Example 3: C++ library callable from C

// mylib.h
#ifdef __cplusplus
extern "C" {
#endif

void my_function(int x);

#ifdef __cplusplus
}
#endif

// mylib.cpp
extern "C" void my_function(int x) {
    std::cout << x << std::endl;
}
// ❌ C function compiled as C, declared as C++ in another TU
void c_function();  // expects mangled name

// main.cpp
c_function();  // link error

// ✅ extern "C"
extern "C" void c_function();

int main() {
    c_function();  // OK
}

Mangling examples

// Namespace
namespace MyLib {
    void func() {}
}
// _ZN5MyLib4funcEv

// Class member
class MyClass {
    void func() {}
};
// _ZN7MyClass4funcEv

// Template
template<typename T>
void func(T x) {}
// func<int>: _Z4funcIiEvT_

Common issues

// mylib.c
void my_func() {}

// main.cpp
void my_func();  // C++ expects mangled symbol
my_func();       // link error

// ✅ extern "C"
extern "C" void my_func();

Issue 2: Header guards with C linkage

// myheader.h
#ifdef __cplusplus
extern "C" {
#endif

void c_function();

#ifdef __cplusplus
}
#endif

Issue 3: Overloading with extern “C”

// ❌ extern "C" cannot overload
extern "C" {
    void func(int x);
    // void func(double x);  // error
}

// ✅ Different C names
extern "C" {
    void func_int(int x);
    void func_double(double x);
}

Issue 4: Compiler differences

# GCC/Clang often follow Itanium C++ ABI mangling.
# MSVC uses different rules.
# Mixing .o/.obj from incompatible toolchains can break linking.
#
# In practice: use one compiler (and compatible ABI) per project.

Demangling

# c++filt
echo "_Z4funci" | c++filt
# func(int)

# With nm
nm program.o | c++filt

# objdump
objdump -t program.o | c++filt

FAQ

Q1: Why name mangling?

A:

  • Overloading
  • Namespace disambiguation
  • Type-safe linking

Q2: When is extern “C” used?

A:

  • Calling C libraries
  • Exposing C++ to C
  • Plugin systems with C APIs

Q3: Demangling?

A: Use the c++filt tool.

Q4: Compiler differences?

A: Rules differ; Itanium ABI is common on GCC/Clang.

Q5: Why no overloading in extern “C”?

A: No mangling, so names must be unique.

Q6: Further reading?

A:

  • Linkers and Loaders
  • Itanium ABI documentation
  • GCC documentation

Related: Linking, ABI, extern linkage, compilation process.


Practical tips

Debugging

  • Check compiler warnings first.
  • Reproduce with a minimal case.

Performance

  • Profile before micro-optimizing.
  • Define metrics.

Code review

  • Anticipate common review comments.
  • Follow conventions.

Practical checklist

Before coding

  • Right technique?
  • Maintainable?
  • Performance OK?

While coding

  • Warnings cleared?
  • Edge cases?
  • Errors handled?

During review

  • Clear intent?
  • Enough tests?
  • Documented?

C++, name mangling, linking, overloading, ABI



같이 보면 좋은 글 (내부 링크)

이 주제와 연결되는 다른 글입니다.


이 글에서 다루는 키워드 (관련 검색어)

C++, name mangling, linking, overloading, ABI 등으로 검색하시면 이 글이 도움이 됩니다.