我试着更深入地理解C编译,所以我正在手动进行编译和链接。这是我的代码:
int main()
{
return 0;
}
这是我在我的控制台(Windows)中输入的内容:
gcc -S main.c
as main.s -o main.o
ld main.o
当我尝试链接时,我得到:
main.o:main.c:(text+0x7): undefined reference to `__main'
你没有链接任何必要的支持库。C全局对象,如stdin、stdout、stderr,并不会自己出现。命令参数和环境变量是从操作系统中获取的。在退出时,所有的atexit()
函数都会被调用,而main
的返回代码将传递给exit(return_code)
。 等等。
检查命令gcc -dumpspecs
,gcc -print-libgcc-file-name
。看看该目录中的所有其他库。你会发现许多这些库和目标文件在dumpspecs的输出中引用。我不知道这些规则是什么时候或者如何被解释的,但是你可能可以得到这个想法。如果你深入挖掘,我认为GCC信息页面info gcc
会详细解释它。
info gcc
然后按'g',然后输入'Spec Files'
正如Jonathan Leffler所说,快捷方式是使用verbose选项运行gcc:gcc -v
,然后查看它使用了哪些命令。
main
函数中实际工作的函数,例如:https://gcc.gnu.org/onlinedocs/gccint/Collect2.html - deamentiaemundi__main
是实际的程序入口点。它不是与main()
函数的内部正常名称相同的标识符_main
。 - Luis Colorado
gcc -v main.c
命令可以查看编译器实际运行的命令。请注意,对于ld
,它运行的命令行比您提供的命令复杂得多。 - Jonathan Lefflerld
参数并不总是必需的。一个简单的“Hello, world”程序可以通过以下方式完美地链接:ld -lc -lkernel32 src.o -o src.exe
。 - Ryan B.argc
和argv
参数,正确存储环境,然后调用main()
获取结果代码(如果main()
执行return exit_value;
),并进行适当的_exit(2)
调用(在调用所有atexit(3)
注册调用之后)。这通常由模块如rt.o
、crt.o
等完成,并且是与架构相关的。 - Luis Colorado