为什么名称错位不规范

Voo*_*Voo 32 c++ name-mangling

我只是想知道为什么名称修改从未被C++标准标准化.显然,使用不同的名称修改算法会损害互操作性[1],我认为没有任何优势可以实现定义.

也就是说,与调用约定或基元大小相反,机器本身并不关心甚至不知道如何调用函数.那么为什么它没有标准化,为什么它仍然没有标准化?编译器在版本之间无论如何都改变了规则.

[1]所有出口功能的人都extern "C"说话量大.

Jam*_*nze 23

该标准未涉及实施细节.有许多东西依赖于实现,并且阻止程序一起工作:如何布置类,结构vtable等等.通常,如果编译器改变其中任何一个,它们将改变名称.这是故意的,因为它可以防止链接无效的代码.

给定平台可以定义C++ ABI; 所有遵循它的编译器都会使用兼容的实现,并且具有通用名称.然而,对于平台供应商来说,这是一个问题; 无论出于何种原因,很少有供应商定义了C++ ABI.

原因之所以extern "C"有效,是因为几乎所有平台都定义了C ABI.

  • @JanHudec实际上并没有明确定义`extern"C"`的含义.例如,在没有C编译器的平台上它意味着什么?然而,在实践中,大多数(如果不是所有)平台都定义了C ABI,而"extern"C"`意味着坚持这一点.在这里,名称重整并不是唯一的问题; 我曾经在订单变量被推入堆栈的平台上工作,C和C++之间是不同的.(另外,我使用过的大多数C编译器都会破坏名称.只是以比C++更简单的方式.) (4认同)
  • 应该补充的是,即使修改是标准化的,也需要`extern"C"`,因为C不做任何修改,C++必须支持重载函数,所以符号在任何情况下都是不同的. (2认同)

Max*_*ert 18

标准实际上并不需要名称修改.就此而言,标准不要求IEEE浮点数,或二进制补码整数或任何其他数量的东西.

在它可以依赖的广泛的ABI之前,GCC实际上不会使用与其竞争对手不同的名称重整计划:

G ++没有像其他C++编译器那样进行名称修改.这意味着使用一个编译器编译的目标文件不能与另一个编译器一起使用.

这种效果是有意的,以保护您免受更微妙的问题.编译器在C++实现的许多内部细节方面有所不同,包括:如何布置类实例,如何实现多重继承,以及如何处理虚函数调用.如果名称编码相同,那么您的程序将链接到其他编译器提供的库 - 但程序在运行时会崩溃.然后在链接时检测不兼容的库,而不是在运行时检测.

名称修改也比许多程序员意识到的要复杂得多.例如,标准如何为C++可以运行的所有平台指定可接受的调用约定stdcall即使RISC系统通常在寄存器而不是堆栈中传递参数,RISC系统是否还需要支持x86 ?