关于C++中名称修改的问题

Tim*_*Tim 23 c c++ linker compilation name-mangling

我正在尝试学习和理解C++中的名称修改.以下是一些问题:

(1)来自devx

当全局函数被重载时,为每个重载版本生成的受损名称是唯一的.名称修改也适用于变量.因此,局部变量和具有相同用户给定名称的全局变量仍然会获得明显的错位名称.

除了重载函数和同名全局变量和局部变量之外,还有其他使用名称修改的示例吗?

(2)来自维基

需要出现这样的情况:语言允许使用相同的标识符命名不同的实体,只要它们占用不同的命名空间(其中命名空间通常由模块,类或显式命名空间指令定义).

我不明白为什么名字改编仅适用于该情况下,当识别属于不同的命名空间,因为重载函数可以在同一个命名空间和相同名称的全局和局部变量,也可以在相同的空间.怎么理解这个?

具有相同名称但在不同范围内的变量是否也使用名称修改?

(3)C有名称错误吗?如果没有,当一些全局和局部变量具有相同名称时,它如何处理?C没有重载功能,对吧?

感谢致敬!

Nik*_*sov 27

C没有进行名称修改,虽然它确实在函数名前面加了一个下划线,所以printf(3)它实际上是_printf在libc对象中.

在C++中,故事是不同的.它的历史是最初Stroustrup创建了"C with classes"或cfront,一个将早期C++转换为C的编译器.然后其他工具--C编译器和链接器将用于生成目标代码.这暗示C++名称必须以某种方式转换为C名称.这正是mangling的名字.它为每个类成员和全局/命名空间函数和变量提供唯一的名称,因此命名空间和类名(用于解析)和参数类型(用于重载)以某种方式包含在最终的链接器名称中.

使用这样的工具很容易看到nm(1)- 编译C++源代码并查看生成的符号.以下是关于GCC的OSX:

namespace zoom
{
    void boom( const std::string& s )
    {
        throw std::runtime_error( s );
    }
}

~$ nm a.out | grep boom
0000000100001873 T __ZN4zoom4boomERKSs
Run Code Online (Sandbox Code Playgroud)

在C和C++中,本地(自动)变量不产生符号,而是存在于寄存器或堆栈中.

编辑:

局部变量在结果对象文件中没有名称,仅仅是因为链接器不需要知道它们.所以没有名字,没有错误.其他一切(链接器必须查看)在C++中被命名为.

  • 是的,我通常称它为*痛*虽然...... :) (7认同)
  • 如果您有嵌套的模板实例,这会更有趣:-) (3认同)
  • C 中的前导下划线仅出现在少数奇怪的平台上,这与一般规则相去甚远。 (2认同)

egr*_*nin 18

Mangling就是编译器如何让链接器满意.

在C中,无论如何都不能有两个具有相同名称的函数.这就是链接器编写的假设:唯一名称.(您可以在不同的编译单元中使用静态函数,因为链接器不关心它们的名称.)

在C++中,只要具有不同的参数类型,就可以拥有两个具有相同名称的函数.所以C++ 以某种方式函数名称与类型组合在一起.这样链接器将它们视为具有不同的名称.

请注意,名称如何被破坏并不重要,实际上每个编译器都会以不同方式执行.重要的是,具有相同基本名称的每个函数都以某种方式对于链接器而言是唯一的.

您现在可以看到,在混合中添加名称空间和模板不断扩展原则.

  • "请注意,名称如何被破坏并不重要".它很重要 - 例如,当您链接由不同编译器编译的库时.这就是为什么许多C++库都有许多版本,一个用于MSVC,一个用于mingw/gcc等. (2认同)
  • 我的意思是:*精确*的修改方式对程序员*你*来说并不重要。 (2认同)

Kat*_*ory 9

从技术上讲,它是"装饰".它听起来不那么粗糙,但也有一些暗示CreditInterest可能会被重新排列,IntCrederestit而实际发生的更像_CreditInterest@4是,可以说,"装饰"而不是被破坏.也就是说,我称它为mangling :-)但如果你搜索"C++名称装饰",你会发现更多的技术信息和例子.


Don*_*nie 5

除了重载函数和同名全局变量和局部变量之外,还有其他使用名称修改的示例吗?

C++ 总是破坏所有符号.它对编译器来说更容易.通常,修改会对参数列表或类型进行编码,因为这些是需要修改的最常见原因.

C不会破坏.范围确定用于控制对同名的本地和全局变量的访问.