修饰名Decorated Names

C 和 C++ 程序中的函数、数据和对象均在内部由其修饰名表示。Functions, data, and objects in C and C++ programs are represented internally by their decorated names. 一个修饰名是由编译器创建的对象、 数据或函数定义在编译期间已编码的字符串。A decorated name is an encoded string created by the compiler during compilation of an object, data, or function definition. 它记录名称以及调用约定、类型、函数参数和其他信息。It records calling conventions, types, function parameters and other information together with the name. 此名称修饰,也称为名称重整、 帮助链接器查找正确的函数和对象链接可执行文件时。This name decoration, also known as name mangling, helps the linker find the correct functions and objects when linking an executable.

修饰的命名约定在各种版本的 Visual Studio 中,已更改,并在不同的目标体系结构上也可能不同。The decorated naming conventions have changed in various versions of Visual Studio, and can also be different on different target architectures. 若要正确链接使用 Visual Studio 中,C 创建的源文件和C++应使用相同的编译器工具集、 标志和目标体系结构编译 Dll 和库。To link correctly with source files created by using Visual Studio, C and C++ DLLs and libraries should be compiled by using the same compiler toolset, flags, and target architecture.

备注

使用 Visual Studio 2015 构建的库可供使用 Visual Studio 2017 或 Visual Studio 2019 生成应用程序。Libraries built with Visual Studio 2015 can be consumed by applications built with Visual Studio 2017 or Visual Studio 2019.

使用修饰名Using decorated names

通常情况下,无需知道修饰名也可编写已成功编译和链接的代码。Normally, you don't have to know the decorated name to write code that compiles and links successfully. 修饰名是编译器和链接器内部的实现详细信息。Decorated names are an implementation detail internal to the compiler and linker. 通常,这些工具可以处理未修饰形式的名称。The tools can usually handle the name in its undecorated form. 但是,在向链接器和其他工具指定函数名时,有时则需要修饰名。However, a decorated name is sometimes required when you specify a function name to the linker and other tools. 例如,若要匹配重载的 C++ 函数、命名空间成员、类构造函数、析构函数和特殊成员函数,则必须指定修饰名。For example, to match overloaded C++ functions, members of namespaces, class constructors, destructors and special member functions, you must specify the decorated name. 有关选项标志和其他需要修饰名的情形的详细信息,请参阅正在使用的工具和选项的相关文档。For details about the option flags and other situations that require decorated names, see the documentation for the tools and options that you are using.

如果你更改函数名、类、调用约定、返回类型或任何参数,则修饰名也会改变。If you change the function name, class, calling convention, return type, or any parameter, the decorated name also changes. 在这种情况下,你必须获取新的修饰名,并将其用于指定了修饰名的任何位置。In this case, you must get the new decorated name and use it everywhere the decorated name is specified.

在链接到用其他编程语言编写的或使用其他编译器的代码时,名称修饰也很重要。Name decoration is also important when linking to code written in other programming languages or using other compilers. 编译器不同,则使用名称修饰约定不同。Different compilers use different name decoration conventions. 在可执行文件链接到用另一种语言编写的代码时,必须特别留意将导出和导入的名称与调用约定相匹配。When your executable links to code written in another language, special care must be taken to match the exported and imported names and calling conventions. 程序集语言代码必须使用 MSVC 修饰名和调用约定来链接到使用 MSVC 编写的源代码。Assembly language code must use the MSVC decorated names and calling conventions to link to source code written using MSVC.

设置格式的C++修饰名Format of a C++ decorated name

C + + 函数的修饰名包含以下信息:A decorated name for a C++ function contains the following information:

  • 函数名称。The function name.

  • 函数所属的类(如果该函数为成员函数)。The class that the function is a member of, if it is a member function. 这可能包括含有函数所属的类的类,等等。This may include the class that encloses the class that contains the function, and so on.

  • 函数所属的命名空间(如果该函数是命名空间的一部分)。The namespace the function belongs to, if it is part of a namespace.

  • 函数参数的类型。The types of the function parameters.

  • 调用约定。The calling convention.

  • 函数的返回类型。The return type of the function.

修饰名中编码有函数名和类名。The function and class names are encoded in the decorated name. 修饰名的其余部分是具有仅用于编译器和链接器的内部意义的代码。The rest of the decorated name is a code that has internal meaning only for the compiler and the linker. 以下示例介绍的是未修饰和修饰的 C++ 名称。The following are examples of undecorated and decorated C++ names.

未修饰名Undecorated name 修饰名Decorated name
int a(char){int i=3;return i;}; ?a@@YAHD@Z
void __stdcall b::c(float){}; ?c@b@@AAGXM@Z

修饰名的 C 格式Format of a C decorated name

C 函数的修饰形式取决于其声明中使用的调用约定,如下表所示。The form of decoration for a C function depends on the calling convention used in its declaration, as shown in the following table. 这也是在将 C++ 代码声明为具有 extern "C" 链接时使用的修饰格式。This is also the decoration format that is used when C++ code is declared to have extern "C" linkage. 默认调用约定是 __cdeclThe default calling convention is __cdecl. 请注意,在 64 位环境中,不修饰函数。Note that in a 64-bit environment, functions are not decorated.

调用约定Calling convention 字体效果Decoration
__cdecl 前导下划线 (_)Leading underscore (_)
__stdcall 前导下划线 (_) 和尾随 at 符号 (@) 后跟十进制中的参数列表中的字节数Leading underscore (_) and a trailing at sign (@) followed by the number of bytes in the parameter list in decimal
__fastcall 前导空格和尾随 at 符号 (@) 后接一个十进制数字表示的参数列表中的字节数Leading and trailing at signs (@) followed by a decimal number representing the number of bytes in the parameter list
__vectorcall 两个尾随 at 符号 (@@) 后接参数列表中的字节的十进制数字Two trailing at signs (@@) followed by a decimal number of bytes in the parameter list

查看修饰名Viewing decorated names

在编译包含数据、对象或者函数定义或原型的源文件之后,可以获取符号名称的修饰形式。You can get the decorated form of a symbol name after you compile the source file that contains the data, object, or function definition or prototype. 若要检查你的程序中的修饰名,可以使用以下方法之一:To examine decorated names in your program, you can use one of the following methods:

若要使用列表查看修饰名To use a listing to view decorated names

  1. 通过编译包含数据、 对象或函数定义或原型的源文件生成列表列出文件类型设置为包含源代码的程序集的编译器选项 (/FAs)。Generate a listing by compiling the source file that contains the data, object, or function definition or prototype with the Listing File Type compiler option set to Assembly with Source Code (/FAs).

    例如,输入cl /c /FAs example.cpp在开发人员命令提示符下,若要生成列表文件 example.asm。For example, enter cl /c /FAs example.cpp at a developer command prompt to generate a listing file, example.asm.

  2. 在生成的列表文件中,找到以 PUBLIC 开头、分号结尾且后接未修饰的数据或函数名的行。In the resulting listing file, find the line that starts with PUBLIC and ends a semicolon followed by the undecorated data or function name. PUBLIC 和分号之间的符号即为修饰名。The symbol between PUBLIC and the semicolon is the decorated name.

若要使用 DUMPBIN 查看修饰名To use DUMPBIN to view decorated names

  1. 若要查看.obj 或.lib 文件中的导出的符号,请输入dumpbin /symbols``objfile开发人员命令提示符处。To see the exported symbols in an .obj or .lib file, enter dumpbin /symbols objfile at a developer command prompt.

  2. 若要查找符号的修饰形式,请查找括号中的未修饰名。To find the decorated form of a symbol, look for the undecorated name in parentheses. 修饰的名位于同一行中后一个管道, (|) 字符和未修饰名称的前面。The decorated name is on the same line, after a pipe (|) character and before the undecorated name.

查看未修饰名Viewing undecorated names

可以使用 undname.exe 将修饰名转换为其未修饰形式。You can use undname.exe to convert a decorated name to its undecorated form. 此示例演示其工作原理:This example shows how it works:

C:\>undname ?func1@a@@AAEXH@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?func1@a@@AAEXH@Z"
is :- "private: void __thiscall a::func1(int)"

请参阅See also

其他 MSVC 生成工具Additional MSVC Build Tools
使用 extern 指定链接Using extern to Specify Linkage