stanford-oval/wikipedia huggingface dataset:
Visual C++名字修饰
C++语言name mangling概述 > 函数的name mangling

函数需要分配内存空间以容纳函数的代码，函数的名字实际上都是lvalue，即指向一块可执行内存空间的起始地址。而函数模板的实例化(function template instantiation)，也是lvalue，需要分配内存空间存储实例化后的代码，其name mangling在模板实例化的名字编码中详述。
<全局函数的name mangling> ::= ?<function name>@ [<namespace>@]∞0 @ <func modifier> 
         <calling conv> [<storage ret>] <return type> <parameter type>∞1 <throw type> 
 <成员函数的name mangling> ::= ?<function name>@ [<namespace>@]∞0 @ <func modifier> 
         [<const modifier>]<calling conv> [<storage ret>] <return type> 
         <parameter type>∞1 <throw type>
其中，<func modifier>给出了函数是near或far、是否为静态函数、是类成员函数还是全局函数、是否为虚函数、类成员函数的访问级别等基本信息。需要注意，far属性仅适用于Windows 16位环境，32位或64位环境下使用扁平(flat)内存地址模型，函数只能具有near属性。
类成员函数的<const modifier>是指是否为只读成员函数(constant member function). 如果不是const，则编码为A；如果是const，则编码为B；如果是类的静态成员函数，则省略该项，因为静态成员函数没有this指针，无法修改类对象的数据。
<calling conv>是指函数的调用协议。详见调用协议的编码。常见的调用协议的编码为：__cdecl是A, __pascal是C, __thiscall是E, __stdcall是G, __fastcall是I。在Windows 64位编译环境中唯一允许的调用协议的编码是A（详见64位程序的调用约定）。
[<storage ret>]是指函数的返回值的是否有const或volatile属性：
<storage ret> ::= ？<CV Modifier>
如果函数的返回值不具有const或volatile性质，那么该项在编码中被省略；但是如果函数的返回类型是class、struct或union等复合数据类型，此项在编码中是必需的，不能省略。
<return type>是函数的返回值的数据类型，详见类型的编码表示。
<parameter type>是函数的形参列表(parameter list)的数据类型的编码。按照形参从左到右顺序给每个参数的数据类型编码，详见类型的编码表示。参数类型列表的编码为：
X (即函数没有参数，或者说参数为void，该编码也是列表的结束标志)
type1 type2 ... typeN @ (正常N个形参. 以@作为列表的结束标志)
type1 type2 ... Z (形参表最后一项为...，即ellipsis，其编码Z也标志着列表的结束)
<throw type>是函数抛出异常的说明，即异常规范(exception specification)。截至Visual C++ 2010，仍是接受但没有实现异常规范。因此这一项编码仍然保持为字符Z。
举例：
void Function1 (int a, int * b); /*mangled as ?Function1@@YAXHPAH@Z 
                                 其中 Y: 全局函数
                                      A: cdecl调用协议
                                      X: 返回类型为void
                                      H: 第一个形参类型为int
                                      PAH：第二个形参类型为整形指针
                                      @： 形参表结束标志
                                      Z: 缺省的异常规范 */
int Class1::MemberFunction(int a, int * b); /* mangled in 32-bit mode as 
                                               ?MemberFunction@Class1@@QAEHHPAH@Z
                                  其中 Q: 类的public function
                                      A: 成员函数不是const member function
                                      E: thiscall调用协议
                                      H: 返回值为整形
                                      H: 第一个形参类型为整形
                                      PAH: 第二个形参为整形指针 */
C++语言name mangling细节 > 名字的编码

C++程序中，需要考虑的具有全局存储属性的变量名字及函数的名字。这些名字受namespace、class等作用域(scope)的限定。因此，带完整限定信息的名字定义为：
<Qualified Name> ::= <Basic Name> [<Qualifier>]∞0 @
 <Basic Name> ::= <Name Fragment> | <Special Name>
 <Qualifier> ::= <namespace> | <class name> | <Template Instantiation> 
                | <Numbered Namespace> | <Back Reference> | <Nested Name>
其中，<Name Fragment>是组成名字标识符的ASCII码串，规定必须以@作为结尾后缀。<Special Name>是指构造函数、析构函数、运算符函数(operator function)、虚表(vtable)等内部数据结构等，详见特殊名字的编码。
<namespace>与<class name>就是指C++程序中的名字空间与类。<Template Instantiation>是指实例化后的函数模板或类模板，详见模板实例化的名字编码。<Numbered Namespace>是对一个函数内部用花括号{ ... }给出的不同的作用域(scope)的编号表示，详见编号名字空间。<Back Reference>是对一个mangled name的ASCII码串中重复出现的类型或名字的简写表示方法，详见重复出现的名字与类型的简写表示。<Nested Name>是对静态局部变量所在的函数名的表示方法，详见嵌套的名字。
C++语言name mangling细节 > 名字的编码 > 数的编码

Visual C++的name mangling，有时会用到数(number)，例如多维数组的维数等。数的编码使用一套独特的方法：
1-10 编码为 0-9，这节省了最常用的数的编码长度；
大于10的数编码为十六进制，原来的十六进制数字0-F用A-P代替，不使用前缀0或0x，使用后缀@作为结束标志；
0编码为A@；
负数编码为前缀?后跟相应的绝对值(absolute value)的编码。
例如，8编码为7。29110编码为BCD@。-1510编码为?P@。
C++语言name mangling细节 > 名字的编码 > 特殊名字的编码

特殊名字(special names)是指类的构造函数、析构函数、运算符函数、类的内部数据结构等的名字，表示为前缀?后跟编码。已知的编码：
| 编码字符 | 不带下划线(_)的含义 | 前置下划线(_)的含义 | 前置双下划线(__)的含义 |
| --- | --- | --- | --- |
| 0 | Constructor | operator /= |  |
| 1 | Destructor | operator %= |  |
| 2 | operator new | operator >>= |  |
| 3 | operator delete | operator <<= |  |
| 4 | operator = | operator &= |  |
| 5 | operator >> | operator |= |  |
| 6 | operator << | operator ^= |  |
| 7 | operator ! | 'vftable' |  |
| 8 | operator == | 'vbtable' |  |
| 9 | operator != | 'vcall' |  |
| A | operator[] | 'typeof' | 'managed vector constructor iterator' |
| B | operator returntype | 'local static guard' | 'managed vector destructor iterator' |
| C | operator -> | 'string'(Unknown) | 'eh vector copy constructor iterator' |
| D | operator * | 'vbase destructor' | 'eh vector vbase copy constructor iterator' |
| E | operator ++ | 'vector deleting destructor' |  |
| F | operator -- | 'default constructor closure' |  |
| G | operator - | 'scalar deleting destructor' |  |
| H | operator + | 'vector constructor iterator' |  |
| I | operator & | 'vector destructor iterator' |  |
| J | operator ->* | 'vector vbase constructor iterator' |  |
| K | operator / | 'virtual displacement map' |  |
| L | operator % | 'eh vector constructor iterator' |  |
| M | operator < | 'eh vector destructor iterator' |  |
| N | operator <= | 'eh vector vbase constructor iterator' |  |
| O | operator > | 'copy constructor closure' |  |
| P | operator >= | 'udt returning' (prefix) |  |
| Q | operator , | Unknown |  |
| R | operator () | RTTI-related code (see below) |  |
| S | operator ~ | 'local vftable' |  |
| T | operator ^ | 'local vftable constructor closure' |  |
| U | operator | | operator new[] |  |
| V | operator && | operator delete[] |  |
| W | operator || |  |  |
| X | operator *= | 'placement delete closure' |  |
| Y | operator += | 'placement delete[] closure' |  |
| Z | operator -= |  |  |
虚表的mangled name是::= ??_7[ <class name> ]∞0 @6B@,
前缀_P用在?_PX之中. 其含义未知。
下表是RTTI相关的编码，都是在_R后跟一个数字. 有些编码还后跟参数.
| 编码 | 含义 | 尾部参数 |
| --- | --- | --- |
| _R0 | type 'RTTI Type Descriptor' | Data type type. |
| _R1 | 'RTTI Base Class Descriptor at (a,b,c,d)' | Four encoded numbers: a, b, c and d. |
| _R2 | 'RTTI Base Class Array' | None. |
| _R3 | 'RTTI Class Hierarchy Descriptor' | None. |
| _R4 | 'RTTI Complete Object Locator' | None. |
C++语言name mangling细节 > 名字的编码 > 模板实例化的名字编码

函数模板实例化后，就是一个具体的函数。类模板实例化后，就是一个具体的类数据类型。
<类模板实例化的名字> ::= ?$ <类模板的名字> <模板实参的编码>  
<函数模板实例化的名字> ::= ?$ <函数模板的名字> <模板实参的编码> 
<函数模板实例化的名字manging> ::= ?$ <函数模板的名字> <模板实参的编码> <函数的类型信息>
模板的名字以前缀?$开始。?$ <函数模板的名字> <函数模板实参的编码>可以代替<function name>，?$ <类模板的名字> <类模板实参的编码>可以代替<class name>。
模板实参(template argument)，可以分为类型名字(typename)与非类型(non-type)的常量两类。如果是类型名字或类作为模板实参，那么其编码格式详见类型的编码表示。如果模板实参是常量(constant)，则已知的编码格式列为下表：
| 编码 | 含义 |
| --- | --- |
?x: anonymous type template parameter x ('template-parameter-x')
$0a: 整数值a
$2ab: 实数值a × 10b-k+1, where k是无符号整数a的十进制的位数
$Da: anonymous type template parameter a ('template-parametera')
$Fab: 2-tuple {a,b} (unknown)
$Gabc: 3-tuple {a,b,c} (unknown)
$Hx: (unknown)
$Ixy: (unknown)
$Jxyz: (unknown)
$Qa: anonymous non-type template parameter a ('non-type-template-parametera')
上表中，用a, b, c表示有符号整数，而x, y, z表示无符号整数. 这些有符号整数或无符号整数的编码格式，详见数的编码。上表中，实数值的编码表示$2ab，a、b都是有符号整数，但计算实数的值时，实际上规范到以10为基数的科学计数法的表示形式。
例如：
template<class T> class one{
	int i;
};

one<int> one1; // mangled as ?one1@@3V?$one@H@@A 
           //3V...@A表示这是一个全局的类对象，其中的@是类的编码的结束标志；
           //类名为one<int>，编码是?$one@H@，其中one@是模板的名字，
           //H是模板实参int，其后的@是模板实参表结束标志
             
             
class Ce{};
one<Ce> another; /* mangled as ?another@@3V?$one@VCe@@@@A */
           //注意，倒数第1个@表示整个(模板实例)类的结束；
              //     倒数第2个@表示模板实参表的结束；
              //     倒数第3个@表示类Ce的限定情况的结束(此处限定为空，即Ce的作用域是全局)；
               //    倒数第4个@表示类名码串的结束
C++语言name mangling细节 > 名字的编码 > 编号名字空间

编号名字空间(numbered namespace)用于指出函数静态局部变量包含在函数的哪个内部作用域中。之所以需要引入编号名字空间，是为了区分函数内部的不同作用域，从而可以区分包含在不同作用域中但同名的变量，详见下例。其编码格式为前缀?后跟一个无符号数，无符号数的编码参见数的编码小节。
特例情况是, 以?A开始的编号名字空间, 是('anonymous namespace').
例如：
int func()
{
 static int i;	// mangled as ?i@?1??func@@YAHXZ@4HA  内部表示为`func'::`2'::i
	     // ?1表示第2号名字空间；?func@@YAHXZ@是函数的mangled名字；4表示静态局部变量
 {
  static int i; // mangled as ?i@?2??func@@YAHXZ@4HA  内部表示为`func'::`3'::i
	              // ?3表示第3号名字空间
	}
	return 0;
}
C++语言name mangling细节 > 名字的编码 > 重复出现的名字与类型的简写

在对一个名字做mangling时，用简写方法表示非首次出现的同一个名字或同一个类型。整个简写过程需要对ASCII码串做3次扫描处理：
对函数或函数指针的形参表中的重复出现的参数数据类型的编码简写；
把第一步获得结果中重复出现的名字的编码简写；
把第二步获得的结果中的模板实例化(模板名字+模板实参表)内部重复出现的名字的编码简写。
C++语言name mangling细节 > 名字的编码 > 重复出现的名字与类型的简写 > 重复出现的类型的简写

这适用于函数与函数指针的形参列表。只有编码超过一个字符的类型参与简写，包括指针、函数指针、引用、数组、bool、__int64、class、实例化的模板类、union、struct、enum等数据类型。形参表中前10种多字符编码的类型按照出现次序依次编号为0,1,...,9。用单个字符编码的类型不参加编号。对不是该数据类型首次出现的形参，用该类型的单个数字的编号代替该数据类型的多个字符的编码来简写表示。排在前十名之后的多字符编码的数据类型，不再简写。函数的返回值类型不参与此编号及简写。
如果函数的返回类型或者形参是函数指针型，那么函数指针型的形参也参与类型排序编号与简写，但函数指针型的返回值类型不参与类型排序编号与简写。在对类型排序编号时，先编号函数指针型内部的形参的数据类型，再编号函数指针型本身。例如，假如函数的第一个形参是void (__cdecl*)(class alpha, class beta)，那么class alpha编号为0, class beta编号为1, 最后整个函数指针编号为2.
例如：
bool ExampleFunction (int*a, int b, int c, int*d, bool e, bool f, bool*g);  
 // mangled as ?ExampleFunction@@YA_NPAHHH0_N1PA_N@Z
//  其中，_N为返回类型bool，不参与类型简写，不参与编号排序；
//  类型的排序编号：int*为0，bool为1，bool*为2。
//  int的编码为单字符H，因此不参与编号
//  第3个形参不简写，仍为H；第四个形参简写为0，第五个形参简写为1 */    
//
 
 
    
typedef int* (*FP)(int*); /* 该函数指针类型编码为 P6APAHPAH@Z */
//

FP	funcfp (int *, FP) /* mangled as ?funcfp@@YAP6APAHPAH@Z0P6APAH0@Z@Z */
//  其中P6A为函数指针类型的编码前缀
//  其中共出现了5次int* (编码为PAH)
//  第1次为funcfp的返回值类型FP的返回值类型，不参与排序编号与简写；
//  第2次为funcfp的返回值类型FP的形参，参与排序编号，编号为0，
//       因为是该类型int*的首次作为形参出现，不简写，仍编码为PAH
//  第3次为funcfp的第一个形参，简写为0；
//  第4次为funcfp的第二个形参的返回值类型，不参与排序编号与简写；
//  第5次为funcfp的第二个形参的参数，简写为0 
{return 0;}
C++语言name mangling细节 > 名字的编码 > 重复出现的名字与类型的简写 > 重复出现的名字的简写

在对码串完成重复出现的类型的简写后，再对结果中所有不同的名字排序编号，从0编号到9。排在前10个之后的名字不再编号、简写。这里的名字是指函数、class、struct、union、enum、实例化的带实参的模板等等的以@作为结尾后缀的名字。例如，在alpha@?1beta@@(即beta::'2'::alpha)中, 0指代alpha@, 1指代beta@，?1是编号名字空间‘2’的编码. 特殊名字、编号名字空间的名字都不参加此轮名字的排序编号与简写。
例如：
class C1{
	class C2{};
};

union C2{};

void func(C2,C1::C2) /* mangled as ?func@@YAXTC2@@V1C1@@@Z */
               //其中，func的形参表是TC2@@V1C1@@@
               //TC2@@是第一个形参union C2；
               //V1C1@@是第二个形参C1::C2，其中V表示这是class，
               //首个1表示是编号为1的名字(即C2@)重复出现，随后的C1@表示C2的限定域为C1
               //随后的@表示限定域的嵌套结束。注意，该字串中编号为“0”的名字是func@  
{}
对于实例化模板，模板名字后跟模板实参作为一个整体视作一个名字，参加此轮排序编号与简写。而模板实参表中的参数序列，单独处理它的编号及简写。例如：
template<class T> class tc{
       public: void __stdcall func(tc<T>){};
};

int main(int argc, char *argv[])
{
	tc<int> ins;
	ins.func(ins); /* tc<int>::func(tc<int>) mangled as ?func@?$tc@H@@QAEXV1@@Z */
	                  //其中，?$tc@H@表示实例化的类模板tc<int>，里面的H表示模板实例化的实参是整型
	                  //Q表示public的成员函数；A表示非只读成员函数；E表示thiscall
	                  //X表示函数返回类型void；
	                  //V1@表示形参为一个class，class的名字为''1''号名字，本例中即tc<int>的编码?$tc@H@；
	                  //注意，本例中''0''号名字是函数名，即func@
	                  //最后一个@表示函数的形参表结束；Z表示缺省的exception specification
	return 0;
}
C++语言name mangling细节 > 名字的编码 > 重复出现的名字与类型的简写 > 模板实例化时重复出现的实参的简写

模板实例化的名字编码，基本上就是用模板的名字与模板实参作为一个整体，当作<func name>或<class name>使用。因此模板实例化的名字在参与完成重复出现的类型简写与重复出现的名字简写两步处理之后，再单独处理模板实例化的模板实参表，对其内部重复出现的名字的编号与简化。其方法与重复出现的名字简写的处理相同。
例1：
template<class T1, class T2> class tc{
	int i;
     public: void __stdcall func(tc<T1,T2> p1,tc<T1,T2> p2){};
};

class Ce{};

int main(int argc, char *argv[])
{
    tc<Ce,Ce> ins;
	  ins.func(ins,ins);  /* void tc<Ce,Ce>::func(tc<Ce,Ce>,tc<Ce,Ce>) 
	                  mangled as ?func@?$tc@VCe@@V1@@@QAGXV1@0@Z */
	     //?$tc@VCe@@V1@@表示实例化的类模板tc<Ce,Ce>，其中的V1@是类模板的实参的重复名字简写；
	     //函数func的作用域是tc<Ce,Ce>,即tc<Ce,Ce>::func编码为func@?$tc@VCe@@V1@@@  ；
//V1@表示成员函数func的第一个形参为一个类，类名为''1''号名字，本例中即tc<Ce,Ce>，这是重复名字的简写；
	     //0表示该函数func的第二个形参与形参表中的''0''号形参相同，即tc<Ce,Ce>，这是重复类型的简写   
 
    return 0;
}
例2：
class class1{
     public:  class class2{} ee2;
};
 
union class2{};

template <class T1, class T2, class T3> void func( T1,T2,T3 ){}

int main(int argc, char *argv[])
{
	class1 a;
	class2 b;
	func<class2, class1::class2, class2>(b,a.ee2,b); 
	   /* func<class2,class1::class2,class2>(class2,class1::class2,class2)
	    mangled as ??$func@Tclass2@@V1class1@@T1@@@YAXTclass2@@V0class1@@0@Z  */
//如果不简写: ??$func@Tclass2@@Vclass2@class1@@Tclass2@@@@YAXTclass2@@Vclass2@class1@@Tclass2@@@Z
//    首先对函数的形参表中重复的类型简写，第3个参数与第1个参数相同，以类型编号0简写；
//    然后对整个字串中重复的名字编号、简写，第1个形参中的名字‘class2@’编号为0，
//        所以函数第2个形参中的‘class2@’被简写为0；
//        这也说明“函数模板名+模板实参”，不作为名字参与编号及简写(但普通函数的名字却是参与名字编号!)，
//        而类模板名+模板实参”却算作单独一个名字而参与编号及简写；
//      之后，对模板实例化名字，即“函数模板名+模板实参”，单独执行重复出现的名字编号及简写，
//          其中的‘class2@’出现3次，后2次被简写为1，这也说明在模板实例化名字内部，
//          仅执行重复名字的简写，不执行重复类型的简写 

	return 0;
}
例3：
class class1{
public: class name9{} ee;
};

template <class T> void name9 ( T p1){}

int main(int argc, char *argv[])
{
	class1 vv;
 	name9<class1::name9>(vv.ee); /* void name9<class1::name9>(class1::name9) 
 	      mangled as ??$name9@V0class1@@@@YAXVname9@class1@@@Z */
// 	      此例说明模板实例化在做重复名字简化时，
// 	      模板实参中的name9与模板名字name9相同，因而简化为编号0 
    return 0;
}
C++语言name mangling细节 > 数据类型的编码表示

这里所说的类型，包括数据类型、函数指针的类型、函数模板、类模板等不需要分配内存空间的一些概念属性。类型是数据对象与函数这两类实体的属性。
| 编码 | 不带下划线(_)的含义 | 前置下划线(_)的含义 |
| --- | --- | --- |
|  ? | 用于表示模板 |  |
| $ | 用于表示模板 | __w64 (prefix) |
| 0-9 | Back reference即用于重复出现的类型或名字的简写 |  |
| A | Type modifier (reference) |  |
| B | Type modifier (volatile reference) |  |
| C | signed char |  |
| D | char | __int8 |
| E | unsigned char | unsigned __int8 |
| F | short | __int16 |
| G | unsigned short | unsigned __int16 |
| H | int | __int32 |
| I | unsigned int | unsigned __int32 |
| J | long | __int64 |
| K | unsigned long | unsigned __int64 |
| L |  | __int128 |
| M | float | unsigned __int128 |
| N | double | bool |
| O | long double | Array |
| P | Type modifier (pointer) |  |
| Q | Type modifier (const pointer) |  |
| R | Type modifier (volatile pointer) |  |
| S | Type modifier (const volatile pointer) |  |
| T | union |  |
| U | struct |  |
| V | class |  |
| W | enum | wchar_t |
| X | void, Complex Type (coclass) | Complex Type (coclass) |
Y: Complex Type (cointerface)
| Z | ... (ellipsis) |  |
对于简单的数据类型，其编码往往就是一个字母。如int类型编码为X。对各种衍生的数据类型（如指针）、复合的数据类型（如类）、函数指针、模板等，在下文中分述。
X表示void 仅当用于表示函数的返回类型、形参表的终止或指针的基类型, 否则该编码表示cointerface. 代码 Z (表示ellipsis)仅用于表示不定长度的形参列表(varargs).
C++语言name mangling细节 > 数据类型的编码表示 > 指针、引用、数组的类型编码

<指针类型的编码> ::= <type modifier> <CV Modifier> <base type>
 <左值引用类型的编码> ::= <type modifier> <CV Modifier> <base type>
 <右值指针类型的编码> ::= $$Q <CV Modifier> <base type>
 <一维数组类型的编码> ::= <指针类型的编码>
 <多维数组类型的编码> ::= <type modifier> <CV Modifier> <Array property><base type>
其中<type modifier>作为前缀，用于区分各种情况的指针、引用、数组。指针自身是const还是volatile等访问属性，由<type modifier>确定。共有八种情况：
|  | none | const | volatile | const volatile |
| --- | --- | --- | --- | --- |
| Pointer | P | Q | R | S |
| Reference | A |  | B |  |
| none | ?, $$C |  |  |  |
<CV Modifier>表示所指向的基类型(Referred type)是否具有const或volatile等访问属性，详见小节：<CV Modifier>。
<base type>表示指针或引用的基类型(Referred type)，或数组的成员类型(element type)。其编码详见数据类型的编码表示。
<Array property>表示多维数组的基础维度信息，其格式为：Y<数组总的维数-1><第2维的长度>...<最后的第N维的长度>。注意，这里使用的数字，要用Visual C++ name mangling特有的数字编码方法，详见数的编码。可见，C++语言的数组是对连续存储数据的内存的直接随机访问(random access)的手段；因此一维数组视作指针，数组访问是否越界，完全由编程者负责；而对多维数组，必须知道除了第一维之外其它各维的长度，才能做到直接随机访问，所以多维数组作为函数形参时，必须已知其除了第一维之外其它各维的长度（以及总的维数），这些信息都被编入了数组的mangled name中。
对于函数指针类型的编码，其<base type>为函数调用接口信息，包括使用的调用协议、返回值类型、形参类型、允许抛出的异常等，详见函数指针类型的编码。类成员指针的类型编码，详见类成员指针的类型编码。类成员函数指针的类型编码，详见类成员函数指针的类型编码。
2003年x86-64位处理器问世后，第一批64位Windows平台的C++编译器曾经使用_O作为数组类型的前缀修饰符(type modifier). 但不久就改回了32位Windows平台C++编译器使用的P前缀.
需注意的是，全局数组类型被编码为P(指针型)，同时作为函数形参的数组类型被编码为Q(常量指针). 这与其本来含义恰恰相反——全局数组型的变量名字表示某块内存地址，该名字不能再改为指向其它内存地址；而作为函数形参的数组型变量的名字所表示的内存地址是可以修改的。但数组类型这种编码方法已经被各种C++编译器广泛接受。显然，这是为了与老的代码保持向后兼容。例如：
int ia[10];                                 //ia是数组类型的非函数形参的变量
//
int main(int argc, char *argv[]) //argv是数组类型的形参, 其类型为 (char *)[]
{
  int j=*(ia++);                              //编译错误！ia是只读的lvalue，不能完成地址的++操作
  char *c= *(argv++);                         //编译正确！argv是可以修改的lvalue
  return 0;
}
例如：
typedef int * p1; // coded as PAH 其中P表示default访问属性的指针，
                  //A表示对基类型的default访问属性，H表示基类型为int
typedef const int * p2; //coded as PBH 其中B表示基类型的const访问属性
typedef volatile int *p3; //coded as PCH 其中C表示基类型的volatile访问属性
typedef volatile const int *p4; //coded as PDH 其中D表示基类型的const volatile访问属性
typedef int * const p5; //coded as QAH 其中Q表示是const pointer
typedef int * volatile p6; //coded as RAH 其中R表示是volatile pointer
typedef int * const volatile p7; //coded as SAH 其中S表示是const volatile pointer
typedef volatile int * const p6; //coded as QCH 例如这是一个外部IO设备输入数据的内存地址
typedef int &r1; // coded as AAH 其中第一个A表示左值引用类型(l-value reference type)
typedef int&& r2; //coded as $$QAH 其中$$Q表示是右值引用类型(r-value reference type)
typedef const int&& r3; //coded as $$QBH 其中B表示基类型是const属性
typedef int[8] a1; // global array coded as PAH
typedef int[10][8] a2; //global array coded as PAY07H 其中Y标志多维数组，0是(维数-1)即1的编码
                       // 7是第二维长度8的编码
typedef int[4][16][5] a3; //global array coded as PAY1BA@4H 其中1为(维数-1)即2的编码
                          //BA@是第二维长度16的编码(16进制的10)，4是第3维长度5的编码
int[7][6] // 作为函数形参时，该数据类型编码为 QAY05H
C++语言name mangling细节 > 数据类型的编码表示 > 函数指针类型的编码

函数指针的类型信息，包括函数返回类型，函数形参类型，调用协议等。以前缀P6开始。各项具体定义可参见函数的类型信息编码：
<global function pointer type info> ::= <type modifier> <CV Modifier> <calling conv> 
    [<storage ret>]<return type>[<parameter type>]∞1<throw type>
一般地，<type modifier>取值为P，意为指针；<CV Modifier>取值为6，意为指针的基类型为near属性的非成员函数。
例如：
typedef const  int (__stdcall *FP) (int i); /* coded as P6G?BHH@Z */
//                                         其中?B表示<storage ret>为const
C++语言name mangling细节 > 数据类型的编码表示 > 类成员指针的类型编码

指向类成员的指针，其编码为
<pointer-to-Member Type> = <type modifier> <CV Modifier>
                            <base-class Qualified Name> <base type>
其中各项的定义详见指针、引用、数组的类型编码。注意，<CV Modifier>是指基类型的属性，常用的值为：Q for default， R for const; S for volatile; T for const volatile。
例如：
class C1{
	int i;
};

typedef int C1::*p; // coded as PQC1@@H
C++语言name mangling细节 > 数据类型的编码表示 > 类成员指针变量的mangled name

类成员指针(pointer to member)的名字mangling的最末尾处对基类型访问属性的编码不同于普通的指针，要在最后加上所指向类的带完整限定信息的名字：
<pointer-to-member name mangling> ::= ?<Qualified Name> <data access modifier>
             <pointer-to-Member Type> <CV Modifier> <base-class Qualified Name>
有的文献称，类成员指针、类成员函数指针的name mangling都必须以Q1@作为结尾，以替代<CV Modifier>。从下述几例可以看出，这种说法是错误的。Q是对所指向的成员类型使用default访问属性，这是最常见的情况。1是该指针所指向类的名字简写，因为在此位置之前该类的名字必然已经出现在该数据类型的编码中，所以此处名字的简写是必然的。但不一定总是简写作1
下例中，成员指针变量的mangled name以S12@结尾：
class outer{
 public:
	class cde{
      public: volatile int i;
  };
};

volatile int outer::cde::* p; // mangled as ?p@@3PScde@outer@@HS12@ 
                              // 其中两个S都是表示基类型为volatile属性
                              // 1是cde@的简写
                              // 2是outer@的简写
例2：
class C1{
  public: int i;
};

C1 const *pi; // ?pi@@3PBVC1@@B 一个简单的指针变量。作为对比

typedef  int C1::*  TP; // coded as PQC1@@H

void func(TP){
 static TP ppp=0; // `func'::`2'::ppp mangled as ?ppp@?1??func@@YAXPQC1@@H@Z@4PQ2@HQ2@ 
                //其中，?ppp@?1??func@@YAXPQC1@@H@Z@表示带作用域限定信息的名字`func'::`2'::ppp
                //4表示静态局部变量；PQ2@H表示成员指针类型，其中的“2”是C1@的简写。
                //注意ppp@编号为0，func@编号为1
                //最后三个字符Q2@表示对基类型“2”(C1@的简写)的访问属性为Q(缺省属性，即非const非volatile)                  
}
C++语言name mangling细节 > 数据类型的编码表示 > 类成员函数指针的类型编码

类成员函数的指针(pointer to member function)，遵从指针类型编码的一般规则。但与函数指针类型的编码相比，多了一项<const Modifier>，表示所指的函数是否为只读成员函数(constant member function)。
<pointer-to-member-function type info> ::= 
              <type modifier> <CV Modifier> <base-class Qualified Name>
              [<const Modifier>] <calling conv> [<storage ret>] <return type> 
              [<parameter type>]∞1  <throw type>
一般地，<type modifier>取值为P，意为指针；<CV Modifier>取值为8，意为指针的基类型为near属性的类成员函数。其它各项取值参见函数的name mangling。
例如：
class C1{
public: void foo(int) const
      {};
};

typedef  void (C1::*TP)(int) const; /* coded as P8C1@@BEXH@Z 
                   其中B表示const member function; E表示thiscall */
C++语言name mangling细节 > 数据类型的编码表示 > 类成员函数的指针变量的mangled name

类成员函数指针(pointer to member function)的名字mangling，对基类型访问属性的编码<CV Modifier>不同于普通的指针，要在最后加上所指向类的带完整限定信息的名字。
<pointer-to-member name mangling> ::= ?<Qualified Name> <data access modifier>
            <pointer-to-Member-Function Type> <CV Modifier> <base-class Qualified Name>
上述定义中，<CV Modifier>取值一般是Q
例如：
class xyz{
public: void foo(int) {};
};

void (xyz::*pfunc)(int) ; /* mangled as ?pfunc@@3P8xyz@@AEXH@ZQ1@ */
//                    其中Q表示对基类型的访问属性为default；1表示被简写的编号为‘1’的名字，即‘xyz@’；
//                  注意，编号为‘0’的名字是‘pfunc@’
C++语言name mangling细节 > 数据类型的编码表示 > 复合类型(union, struct, class, coclass, cointerface)的编码

<复合类型的编码> ::= <复合类型的种类><复合类型的带限定的名字>
其中复合类型的种类作为前缀，union编码为T, struct编码为U, class编码为V, coclass编码为X, cointerface编码为Y。复合类型的带限定的名字<Qualified Name>，是指按照名字所在的名字空间、所属的类，逐级列出限定情况(qualifier)，详见名字的编码。
经常可以看到复合类型的编码以@@两个字符结尾，这是因为第一个@表示复合类型名字的字串结束，第二个@表示限定情况的结束(即作用域为全局，限定情况为空)。
编写代码时，经常要用到类的前向声明(forward declaration)，即提前声明这个名字是个类，但类的成员尚未给出。例如:
class myClassName; //mangled type name is VmyClassName@@
class myClassName::embedClassName; //mangled type name is VembedClassName@VmyClassName@@
C++语言name mangling细节 > 数据类型的编码表示 > 枚举类型(enum)的编码

<枚举类型的编码> ::= W <枚举实际使用的数据类型> <enum-type Qualified Name>
<枚举成员的编码> ::= W <枚举实际使用的数据类型> <enumerator name>@ <enum-type Qualified Name>
其中，W为枚举类型前缀词。<enum-type Qualified Name>为枚举类型的带限定的名字，是指按照名字所在的名字空间、所属的类，逐级列出限定情况(qualifier)，详见名字的编码。枚举实际使用的数据类型，
编码如下：
| 编码 | 对应的实际数据类型 |
| --- | --- |
0: char
1: unsigned char
2: short
3: unsigned short
4: int (generally normal "enum")
5: unsigned int
6: long
7: unsigned long
例如：
enum namex:unsigned char {Sunday, Monday}; // enum-type coded as W4namex@@
看起来Visual C++已经把所有枚举类型用int型实现，因此枚举的基类型(The underlying type of the enumeration identifiers)的编码总是为4
C++语言name mangling细节 > 数据类型的编码表示 > <CV Modifier>

<CV Modifier>用于普通的数据对象，表示其是否具有const、volatile等访问属性；用于指针、数组、引用类型，则表明对基类型的访问属性，而指针自身是否为const、volatile等属性，则专由<type modifier>编码表示。
<CV Modifier>用于函数指针时，表示该指针所指向的基类型是函数。但与指向数据对象的普通指针不同——函数指针指向的基类型（即函数）也有自己的内存空间，只是这块内存空间必定是只读的、可执行的，因此函数指针所指向的基类型内存空间不存在const、volatile等访问属性。
<CV Modifier>的取值情况：
|  | Variable> none | Variable> const | Variable> volatile | Variable> const volatile | Function |
| --- | --- | --- | --- | --- | --- |
| none | A | B, J | C, G, K | D, H, L | 6, 7 |
| __based() | M | N | O | P | _A, _B |
| Member | Q, U, Y | R, V, Z | S, W, 0 | T, X, 1 | 8, 9 |
| __based() Member | 2 | 3 | 4 | 5 | _C, _D |
<CV Modifier>可以有0个或多个前缀:
| Prefix | Meaning |
| --- | --- |
E: type __ptr64
F: __unaligned type
I: type __restrict
C++语言name mangling细节 > 数据类型的编码表示 > <CV Modifier> > __based()属性的变量

指针变量的__based()属性是Microsoft的C++语言扩展. 这一属性编码为:
0 (意味着__based(void))
2<Qualified Name> (意味着__based(<Qualified Name>))
5 (意味着没有__based())
例如：
int *pBased;     // mangled name:  ?pBased@@3PAHA 
int __based(pBased) * pBasedPtr;    // 需要注意Visual C++编译器把这个指针变量的声明解释为：
//         (int __based(pBased) * __based(pBased) pBasedPtr)
//         因此其mangled name: ?pBasedPtr@@3PM2pBased@@HM21@ 
//       其中PM2pBased@@表示这是基于<::pBased>的指针；HM21表示是基于“1”的整型指针，
//       “1”是重复出现的名字的编号简写，这里就是指pBased@ 
//
int __based(void) *pbc; // mangled name: ?pbc@@3PM0HM0 其中的0表示这是__based(void). 
//        编译器把该变量声明解释为(int __based(void) * __based(void) pbc)
C++语言name mangling细节 > 函数的类型信息编码

函数的类型信息，是指调用函数时必须考虑的ABI(Application Binary Interface)，包括调用协议、返回类型、函数形参表、函数抛出异常的说明(exception specification)等，参见函数的name mangling。
C++语言name mangling细节 > 函数的类型信息编码 > <func modifier>

<func modifier>给出了函数是near或far（但far属性仅适用于Windows 16位环境，32位或64位环境下只能函数具有near属性）、是否为静态函数、是否为虚函数、类成员函数的访问级别等信息：
|  | near | far | static near | static far | virtual near | virtual far | thunk near | thunk far |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| private: | A | B | C | D | E | F | G | H |
| protected: | I | J | K | L | M | N | O | P |
| public: | Q | R | S | T | U | V | W | X |
| not member | Y | Z |  |  |  |  |  |  |
上表中的thunk函数，是指在多继承时，由编译器生成的包装函数(warpper function)，用于多态调用实际已被子类对应函数覆盖(overrided)的父类虚函数，并把指向父类的this指针调整到指向子类的起始地址。
C++语言name mangling细节 > 函数的类型信息编码 > 调用协议的编码

| Code | Exported? | Calling Convention |
| --- | --- | --- |
| A | No | __cdecl |
| B | Yes | __cdecl |
| C | No | __pascal __fortran |
| D | Yes | __pascal |
| E | No | __thiscall |
| F | Yes | __thiscall |
| G | No | __stdcall |
| H | Yes | __stdcall |
| I | No | __fastcall |
| J | Yes | __fastcall |
| K | No | none |
| L | Yes | none |
| M | No | __clrcall |
64位编程时，唯一可用的调用协议的编码是A