What is the reason function names are prefixed with an underscore by the compiler?

冷暖自知 提交于 2019-11-27 08:49:05

From Linkers and Loaders:

At the time that UNIX was rewritten in C in about 1974, its authors already had extensive assember language libraries, and it was easier to mangle the names of new C and C-compatible code than to go back and fix all the existing code. Now, 20 years later, the assembler code has all been rewritten five times, and UNIX C compilers, particularly ones that create COFF and ELF object files, no longer prepend the underscore.

Prepending an underscore in the assembly results of C compilation is just a name-mangling convention that arose as a workaround. It stuck around for (as far as I know) no particular reason, and has now made its way into Clang.

Outside of assembly, the C standard library often has implementation-defined functions prefixed with an underscore to convey notions of magicalness and don't touch this to the ordinary programmers that stumble across them.

A lot of compilers used to translate C to assembly language, and then run an assembler on that to generate an object file. It's a lot easier than generating binary code directly. (AFAIK GCC still does this. But it also has its own assembler.) During this translation, function names become labels in the assembly source. If you have a function called (for example) ret, though, some assemblers can get confused and think it's an instruction rather than a label. (YASM does, for example, mostly because labels can appear pretty much anywhere and don't require colons. You have to prepend a $ if you want a label called ret.)

Prepending a character (like, say, an underscore) to the C-generated labels was a whole lot easier than writing one's own C-friendly assembler or worrying about labels clashing with assembly instructions/directives.

These days, assemblers and compilers have evolved a bit, and most people work at the C level or higher anyway. So the original need to mangle names in C is largely gone.

user1910461

At first glance the operating system is a Unix/Unix-like running on a PC. According to me, there is nothing much surprising to find _printf in the generated assembly language. C printf is a function which performs an I/O. So it is the responsibility of the kernel + driver to perform the requested I/O.

The machine instructions path taken on any Unix/Unix-like OS is the following:

printf (C code)-> _printf (libc) -> trap -> kernel + driver work -> return from trap -> return from _printf (libc) -> printf completion and return -> next machine instruction in C code

In the case of this assembly code extract, it looks like the C printf is inlined by the compilateur which caused the _printf entry point to be visible in the assembly code.

To make sure the C printf does not get decorated with a prefix (an underscore in this case), best if searching in all C headers for a _printf with a command like:

find /usr/include -name *.h -exec grep _printf {} \; -print

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!