[2026] C++ Name Mangling Explained: Symbols, extern C, and Linking
이 글의 핵심
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.
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 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
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// 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
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# Compile
g++ -c program.cpp
# Symbols
nm program.o
# Demangle
nm program.o | c++filt
Example 2: extern “C”
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 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
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 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;
}
Example 4: Fixing link errors
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ 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
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 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
Issue 1: Link errors across C and C++
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// 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
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// myheader.h
#ifdef __cplusplus
extern "C" {
#endif
void c_function();
#ifdef __cplusplus
}
#endif
Issue 3: Overloading with extern “C”
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ 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
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 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
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# 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.
Related posts (internal links)
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?