重载名字为什么需要编码

C++允许不同参数类型的函数使用相同源码名字,还允许名字位于不同命名空间或类中。编译后若只保留简单拼写,链接工具就难以区分这些实体;名称修饰将有关名字、类型及作用域信息映射为不同符号。

Itanium C++ ABI用文法规定这类外部名字,通常以_Z开头,再接名字和相应类型编码。它是一种ABI约定,不是所有编译器和语言都必须采用的通用命名方式;命名空间、模板和特殊函数还有各自规则。

参考:[1]

编码哪些信息取决于上下文

在这套ABI中,普通非模板函数的名字编码不包含返回类型,参数中的函数类型或某些模板场景则有不同规则。因此不能把修饰名说成“完整函数声明的逐字复制”,也不能仅靠改返回类型就指望得到一个新的普通重载。

该ABI下具有C语言链接的函数名不按C++函数名规则修饰,全局命名空间中的变量也有不修饰的情况。extern "C"可以约束链接名字,却不会替双方补齐对象布局、调用约定或运行库差异;跨语言接口仍需明确这些条件。

参考:[1]

可读显示与兼容边界

工具可以按对应文法把修饰名解读成较易读的形式,帮助阅读链接错误、符号表和栈信息。这种反解读依赖已知编码规则,并不说明名称修饰原本是在隐藏秘密;不同ABI的符号也不能随意用同一种规则解释。

即使两个编译组件产生相同形式的名字,也仍需匹配类布局、异常处理、运行库与其他ABI要求。修饰名是组件衔接的一部分,既不能替代版本检查,也不代表把名字改成一样就能修复不兼容二进制。

参考:[1]