Gnu编译器的换名规则

GNU C++ 编译器的换名规则 #

全局变量 #

不做任何修改

全局函数 #

_Z开头,然后是函数名字符的个数,接着是函数名,最后是函数参数的别名。

类或命名空间中的变量或函数 #

_ZN开头,然后是变量或函数所在名字空间或类名字的字符长度,然后接着的是真正的名字空间或类名,然后是变量或函数名的长度和变量或函数名,后面紧跟字母E,最后如果是函数的话则跟参数别名,如果是变量则什么都不用加。

构造函数和析构函数 #

_ZN开头,然后是构造函数所在名字空间和类名字的字符长度,然后接着的是真正的名字空间或类名,然后构造函数接C1或者C2,析构函数接D1或者D2,然后加上字母E,最后接函数参数别名结束。

函数的参数 #

是基本类型时 #

参数类型参数别名
voidv
wchar_tw
boolb
charc
signed chara
unsigned charh
shorts
unsigned shortt
inti
unsigned intj
longl
unsigned longm
long long或__int64x
unsigned long long或unsigned __int64y
__int128n
unsigned __int128o
floatf
doubled
long double或__float80e
__float128g

是类或结构体时 #

在类或者结构体名字前加上类或结构体名的字符长度
例如,全局函数int structure_func(int i, struct test s, double d),其经过符号改编后,函数名变成了_Z14structure_funci4testd

是指针(*)时 #

含有指针时,该参数的别名是P(大写)加上该指针指向的参数类型的别名。当参数为指针的指针时,该参数的别名是PP加上所指向的参数类型的别名,以此类推。

是一维数组时 #

和参数是指针的处理方式一样,也是P加上作为参数的数组其元素类型的别名。

是多维数组时 #

第一维可以看做是指针,其它维则看做是数组。
当函数参数中含有多维数组时,以P(代表数组的第一维)开始,后面接A加上各维数组的长度,以_间隔,最后以下划线加数组元素类型的别名结束。
例如,全局函数void multi_array_func(int a[10][10][20][30]),其经过符号改编后,函数名变成了_Z16multi_array_funcPA10_A20_A30_i

含有const修饰符时 #

K(大写)开始,后面接修饰参数类型的别名

是引用(&)时 #

R(大写)开始,后面加上该引用所引用的变量类型的别名。
例如,全局函数void ref_const_func(const int &i),其经过符号改编后,函数名变成了_Z14ref_const_funcRKi

是别的命名空间中的类或结构体 #

该参数的别名是N(大写),加上空间名的长度,再加上空间名,接着是类或结构名的长度和类或结构的名字,最后以E(大写)结束。

总结 #

  1. 除了全局变量不用做改编之外,其它所需要改编符号的时候,都是以_Z开始;
    • 若想表示某个符号是在命名空间或类中的,要以N开始,以E结束;
  2. 所有的名字空间名、类名、函数名或变量名,改编的时候都是名字所包含的字符数加上真正的名字;
    • 所有的名字按照从外层到里层的顺序进行改编;
    • 如果是函数的话,所有的参数按照前后出现的顺序进行改编。

参考资料 #

GNU C++的符号改编机制介绍