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

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

(1)来自devx

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

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

(2)来自Wiki

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

我不太明白为什么名称修改仅适用于标识符属于不同名称空间的情况,因为重载函数可以在同一名称空间中,同名全局变量和局部变量也可以在同一空间中。 怎么理解这个?

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

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

感谢致敬!

C没有进行名称修改,虽然它确实为函数名称预先添加了下划线,因此printf(3)实际上是libc对象中的_printf。

在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 

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

编辑:

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

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

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

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

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

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

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

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

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

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

资料来源: http : //sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

名称修改是C ++编译器使用的过程,为程序中的每个函数赋予唯一的名称。 在C ++中,程序通常至少具有一些具有相同名称的函数。 因此,名称修改可以被认为是C ++中的一个重要方面。

示例:通常,成员名称是通过将成员的名称与类的名称连接而唯一生成的,例如给出声明:

 class Class1 { public: int val; ... }; 

val变得像:

  // a possible member name mangling val__11Class1