为什么C编译器将下划线添加到外部名称?

Mic*_*urr 34 c language-history

我已经在C工作了很长时间以至于编译器通常在一个开头添加一个下划线这一事实extern只是被理解......然而,今天另一个SO问题让我想知道为什么添加下划线的真正原因.一篇维基百科文章称,原因是:

C编译器的常见做法是在所有外部作用域程序标识符之前加上前导下划线,以避免与运行时语言支持的贡献发生冲突

我认为这至少有一个真实的核心,但它似乎并没有真正回答这个问题,因为如果将下划线添加到所有外部,它对防止冲突没有多大帮助.

有没有人有关于领先下划线的理由的良好信息?

增加的下划线部分原因是Unix creat()系统调用不以'e'结尾?我听说某些平台上的早期链接器名称限制为6个字符.如果是这种情况,那么将下划线添加到外部名称似乎是一个彻头彻尾的疯狂想法(现在我只有5个字符可以玩......).

Joh*_*all 18

C编译器的常见做法是在所有外部作用域程序标识符之前加上前导下划线,以避免与运行时语言支持的贡献发生冲突

如果编译器提供运行时支持,您会认为将下划线添加到运行时支持中的少数外部标识符更有意义!

当C编译器首次出现时,在这些平台上用C编程的基本替代方法是用汇编语言编程,并且(并且偶尔仍然)将汇编器和C编写的目标文件链接在一起很有用.所以真的(恕我直言)领先添加到外部C标识符的下划线是为了避免与您自己的汇编代码中的标识符冲突.

(另请参阅GCC的asm标签扩展 ;请注意,这个前置下划线可以被认为是一种简单的名称修改形式.更复杂的语言如C++使用更复杂的名称修改,但这是它开始的地方.)


alv*_*vin 5

如果c编译器总是在每个符号之前添加下划线,那么启动/ c运行时代码(通常用汇编编写)可以安全地使用不以下划线开头的标签和符号(例如符号'start ").

即使你在c代码中编写一个start()函数,它也会在object/asm输出中生成为_start.(请注意,在这种情况下,c代码不可能生成不以下划线开头的符号)因此启动编码器不必担心为每个代码发明模糊的不可能的符号(如$ _dontuse42%$)他/她的全局变量/标签.

因此链接器不会抱怨名称冲突,程序员很高兴.:)

以下内容与编译器在其输出格式中添加下划线的做法不同.

这种做法后来被编成C和C++语言标准的一部分,其中使用前导下划线为实现保留.

对于c系统库和其他系统组件,这是遵循的约定.(以及诸如__FILE__之类的东西).

(请注意,这样的符号(例如:_time)可能会在生成的输出中产生2个前导下划线(__time))