他们说 main()是一个像其他功能一样的函数,但"标记"是二进制中的入口点,是操作的入口点系统可能会找到(不知道)并从那里启动程序。因此,我正在尝试了解有关此功能的更多信息。我做了什么?我在内部使用此代码创建了一个简单的.c文件:
int main(int argc, char **argv) {
return (0);
}
我保存了文件,安装了GCC编译器(在Windows,mingw环境中),并创建了这样的批处理文件:
gcc -c test.c -nostartfiles -nodefaultlibs -nostdlib -nostdinc -o test.o
gcc -o test.exe -nostartfiles -nodefaultlibs -nostdlib -nostdinc -s -O2 test.o
@%comspec%
我这样做是为了获得一个非常简单的编译器和链接器,没有库,没有标题,只是编译器。因此,编译良好,但链接停止了此错误:
test.c:(.text+0xa): undefined reference to '___main'
collect2.exe: error: Id returned 1 exit status
我认为主函数是由链接器导出的,但我认为您不需要任何图书馆,而没有其他有关它的信息。但是看起来确实如此。就我而言,我认为它必须是标准的GCC库,因此我下载了它的源代码并打开了此文件: libgcc2.c 现在,我不知道这是否是构造主函数以通过GCC链接的文件。实际上,我不了解GCC如何使用主要功能。为什么链接器需要GCC标准库?知道MAIN呢?我希望这使我的问题变得非常具体且清晰。谢谢!
当GCC将所有对象文件(test.o)和库形成二进制文件时,它也会预留一个小对象(通常是CRT0.O或CRT1.O),该对象负责致电您的main()
。当您在命令行上添加-v
时,您可以看到GCC在做什么:
$ gcc -v -o test.exe test.o
crt0/crt1进行一些设置,然后调用MAIN。但是链接器最终负责根据操作系统构建可执行文件。使用-v
,您还可以看到目标系统的选项。就我而言,这是针对Linux 64位:-m elf_x86_64
。对于您的系统,这将是-m windows
或-m mingw
。
发生了错误,因为您使用了这两个选项: -nodefaultlibs -nostdlib
这些告诉GCC,它不应使用包含真正称为main()
的代码的libc.a
/c.lib
链接您的代码。简而言之,每个操作系统都略有不同,其中大多数不在乎C和main()
。每个人都有自己的特殊方法来启动一个过程,其中大多数与C API不兼容。
因此,C开发人员的解决方案是将"胶水代码"放入C标准库libc.a
中,其中包含OS期望的接口,创建标准C环境(设置内存分配结构,因此malloc()
将映射OS的OS。内存管理功能,设置stdio等),最终调用main()
对于C开发人员,这意味着他们为操作系统(以及编译器二进制文件)获得libc.a
,并且他们不需要关心设置的工作方式。
混乱的另一个来源是参考的名称。在大多数系统上,main()
的符号名称是_main
(即一个下划线),而__main
是设置代码所调用的内部函数的名称,该函数最终称为真实的main()