名称修饰
名称修饰通常是指 C++ 命名约定,但也可应用于多个 C 情形。 默认情况下,C++ 使用函数名、参数和返回类型来为该函数创建链接器名称。 请考虑以下函数声明:
void CALLTYPE test(void);
下表显示了各种调用约定的链接器名称。
调用约定 | extern "C" 或 .c 文件 |
.cpp 、.cxx 或 /TP |
---|---|---|
C 命名约定 (__cdecl ) |
_test |
?test@@ZAXXZ |
Fastcall 命名约定 (__fastcall ) |
@test@0 |
?test@@YIXXZ |
标准调用命名约定 (__stdcall ) |
_test@0 |
?test@@YGXXZ |
Vectorcall 命名约定 (__vectorcall ) |
test@@0 |
?test@@YQXXZ |
使用 extern "C"
从 C++ 调用 C 函数。 extern "C"
强制对非类 C++ 函数使用 C 命名约定。 请注意编译器开关 /Tc 或 /Tp,它们通知编译器忽略文件扩展名并分别将文件编译为 C 或 C++。 这些选项可能会导致不需要的链接器名称。
具有不匹配的参数的函数原型也会导致此错误。 名称修饰将函数的参数合并到最终修饰的函数名中。 使用与函数声明的参数类型不匹配的参数类型调用函数可能会导致 LNK2001。
目前,在编译器供应商之间,甚至在同一编译器的不同版本之间尚不存在 C++ 命名标准。 链接用其他编译器编译的对象文件可能不会产生相同的命名方案,从而导致无法解析的外部对象。