使用gcc编译时,函数和变量前面是否为"_"?

Pan*_*der 4 c gcc operating-system kernel

我正在使用GCC在Linux环境中学习OS开发.我在Bran的内核开发中了解到,编译时C中的所有函数和变量名都在其相应的汇编源文件中以"_"(下划线)开头.但是当我浏览已编译的C程序的汇编源代码时,我甚至找不到"_main"函数.我执行了以下操作.

cpp sample.c sample.i

gcc -S sample.I

Cra*_*tey 6

这在早期就是如此.给定的C函数foo_foo在汇编程序中显示.这样做是为了避免与手动生成的.s文件发生冲突.

它也将被限制为总共8个字符[链接器限制].

几十年来,情况并非如此.现在,符号不再以前缀为前缀,_可以长于8个字符.


更新:

那么,现在GCC不会在函数和变量前面产生_?

在大多数情况下,没有.IMO,你引用的参考,在这一点上,似乎确实有点过时了.

大多数POSIX系统(例如linux,*BSD)使用gcc[或clang]并且它们会离开_.

当我第一次在C [大约1981年]开始编程时,_仍在使用.这是在AT&T Unix v7,System III和System V上.

IIRC,它在20世纪90年代初期用于更新的系统(如linux).就个人而言,我_从那时起就没有遇到过前缀,但我[大部分]都使用过linux [有时候是cygwin].

一些AT&T Unix衍生系统可能会保留它以实现向后兼容,但最终,大多数人都标准化了"foo is foo".我无法访问OSX,所以我不能排除Johnathan对此的评论.

_自UNIX(大约1970年)的前期已经存在了.这是在我的时间之前,但是,IIRC,Unix最初是用汇编语言编写的.它被转换为C. _用于划分用C语言编写的函数,或用于从C函数调用的asm函数.

那些没有前缀的是"仅限asm"[因为他们可能使用了非标准的调用约定].在当天,一切都很珍贵:RAM,CPU周期等.

因此,asm函数可以/将使用"技巧"来节省资源.几个asm函数可以作为一个组工作,因为他们彼此了解.

如果可以从C调用给定的asm函数,则_前缀符号是C兼容的"包装器"[在prolog/epilog中进行了额外的保存/恢复].

那么,我可以将C程序的主要功能称为"call main"而不是"call _main"?

这是一个相当安全的赌注.

如果您从C调用给定的函数,它将自动执行正确的操作(即添加前缀或不添加前缀).

它只是试图在从手生成的汇编,这个问题调用C函数可能连上来.

所以,对于asm,我只是做了一件简单的事情call main.它适用于大多数[如果不是全部]系统.

如果你想"防弹"你的代码,你可以通过C预处理器(通过.S文件)运行你的asm 并做(例如):

#ifdef C_USES_UNDERSCORE
#define CF(_x)          _##_x
#else
#define CF(_x)          _x
#endif

    call    CF(main)
Run Code Online (Sandbox Code Playgroud)

但是,我认为这太过分了.

它还说明了_前缀的整个问题.在具有大量内存和CPU周期的现代系统中,为什么汇编程序函数必须知道它调用的ABI兼容函数是从C还是手写汇编程序生成的?

  • 它至少取决于平台.在Mac OS X上,如果我编译包含函数`any_function()`的C源文件`any_function.c`,则根据`nm -g any_function.o`,目标文件包含符号`_any_function`. (2认同)