您可以以可移植的方式执行此操作,只需将此头文件包含在您的主程序中:
int nomDePlume(int argc, char *argv[]);
int main(int argc, char *argv[]) { return nomDePlume(argc, argv); }
然后提供您自己的main 变体:
int nomDePlume(int argc, char *argv[]) {
weaveYourMagic();
return 42;
}
这实际上并没有改变可执行文件的入口点(这是非常特定于实现的东西),但它确实让你可以随意调用你的程序入口点(当然,在合法标识符的范围内)。
如果您根本不想要main(即使在头文件中),它会变得有点棘手。
那是因为可执行文件的入口点通常不是 main - 在调用 main 之前发生了相当多的活动,与环境设置和其他事情有关(以及main 退出后的一些拆解内容,例如您的 atexit 处理程序。
换句话说,虽然main 函数可能是您的 C 程序开始的地方,但这与您的可执行文件的开始位置不相同。
作为一个例子,在 Linux 中,ELF 可执行文件格式在标头块的 e_entry 字段中包含一个入口点地址,这是程序加载器在准备好运行可执行文件时跳转到的位置。
设置它通常发生的情况是,您(隐式)链接一些启动代码,如crt0,并且链接器使用已知符号的地址填充e_entry 字段。其中的一个例子是(来自该链接,对 cmets 稍作修改):
.text
.globl _start
_start: # Entry point known to linker.
xor %ebp, %ebp # RBP <- 0, mark end of stack frames.
mov (%rsp), %edi # Get argc from stack (implicitly
# zero-extended to 64-bit).
lea 8(%rsp), %rsi # Take address of argv from stack.
lea 16(%rsp,%rdi,8), %rdx # Take address of envp from stack.
xor %eax, %eax # Per ABI and compatibility with icc.
call main # Three args %edi/%rsi/%rdx (first
# two are C standard).
mov %eax, %edi # Effectively set up _exit(main()).
xor %eax, %eax # Per ABI and compatibility with icc.
call _exit # Terminate the program.
您可以在main 调用的任何一侧看到启动和拆除的事情,这为您提供了一个可能的解决方案。
通过创建您的自己的 crt0,将文本 main 替换为您想要调用的任何内容,并确保链接器使用 您的 crt0 而不是默认一个,你可以让它调用你想要提供的任何函数作为主函数。
但是,除了获得工作保障或在您的同事找不到您的代码从哪里开始时惹恼您的同事之外,您从能够使用任意命名的 main 函数中获得什么并不是很清楚 :-)
如果它是一种教育性的东西,那很好 - 我只是不会在现实世界中这样做。