
在C++中,Name Mangling(名称修饰或名字改编)是一种编译器用来将函数、变量等符号转换为唯一链接器标识符的机制。它的主要目的是支持C++的高级特性,比如函数重载、命名空间、类成员函数等,这些在C语言中并不存在。
为什么需要Name Mangling?
C语言不支持函数重载,所以每个函数名在编译后直接对应一个唯一的符号名。例如,函数void foo()在目标文件中的符号就是_foo(具体前缀可能因平台而异)。
但在C++中,可以有多个同名函数,只要它们的参数列表不同:
void print(int x);void print(double x);
void print(const char* s);
这三个函数都叫print,但参数类型不同。为了让链接器能区分它们,编译器必须把函数名和参数类型等信息编码成一个唯一的符号名。这个过程就是Name Mangling。
立即学习“C++免费学习笔记(深入)”;
函数重载与符号生成
编译器根据函数名、参数类型、所在类、命名空间等信息生成修饰后的符号。例如:
namespace math {void add(int a, int b);
}
可能被mangle成类似:_Z4math3addii(具体格式依赖于编译器和ABI)。
其中:
- _Z:表示这是一个C++ mangled name
- 4math:命名空间“math”,长度为4
- 3add:函数名“add”,长度为3
- ii:两个int类型的参数
这样,即使函数名相同,只要签名不同,生成的符号就不同,链接器就不会冲突。
不同编译器的Mangling规则不同
目前主流编译器(如GCC、Clang)遵循Itanium C++ ABI的mangling规则,Windows上的MSVC则使用自己的一套规则。这意味着:
- 用GCC编译的代码和MSVC编译的代码通常不能直接链接
- mangled name不可移植,不应在代码中硬编码
你可以使用c++filt工具来反解mangled name:
$ c++filt _Z4math3addiimath::add(int, int)
如何避免Name Mangling的影响?
当你希望C++代码能被C语言调用(或反之),就需要关闭Name Mangling。方法是使用extern "C":
extern "C" {void my_c_function(int x);
}
这会告诉编译器:这个函数按C语言方式处理,不进行name mangling,生成的符号就是my_c_function,便于C代码链接。
这在编写库接口、系统调用封装时非常常见。
基本上就这些。Name Mangling是C++实现函数重载等特性的底层支撑,开发者一般不需要手动处理,但在调试链接错误或查看符号表时了解它很有帮助。











