欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

main函数声明

发布时间:2025/3/20 编程问答 82 豆豆
生活随笔 收集整理的这篇文章主要介绍了 main函数声明 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

main函数声明

 

背景:

main函数经常会声明为以下方式:

int main(); int main(int argc, char* argv[]); int main(int argc, char* argv[], char*envp[]);

还有些会将返回类型替换为void,最常见的就是

void main();

 

一、VC如何支持这些不同的main函数声明

main函数是在__tmainCRTStartup中被调用的,__tmainCRTStartup也没有做特别处理。
不同main函数声明被支持是因为main函数是使用__cdecl调用约定的。

__cdecl调用约定由调用方负责参数的压栈和出栈。

__tmainCRTStartup实现在crtexe.c中,其调用main函数的汇编码如下:

mainret = main(argc, argv, envp); 00A4BAEF mov eax,dword ptr [envp (0A572B0h)] 00A4BAF4 push eax 00A4BAF5 mov ecx,dword ptr [argv (0A572B4h)] 00A4BAFB push ecx 00A4BAFC mov edx,dword ptr [argc (0A572ACh)] 00A4BB02 push edx 00A4BB03 call @ILT+1355(_main) (0A41550h) 00A4BB08 add esp,0Ch 00A4BB0B mov dword ptr [mainret (0A572C4h)],eax

 

__tmainCRTStartup做如下处理:

1、按从右到左的顺序将三个参数压栈
2、调用main函数
3、出栈 (简单的将栈指针移上来,上移是因为栈是向下生长的)
4、将存放在eax中的返回值赋给int型的mainret

以下声明也是合法的:

int main(int a, int b, char* c, int d, char* e);

PS:关于为什么__tmainCRTStartup调用的main原型与声明的不一致也能通过编译和链接是因为__tmainCRTStartup已经是编译过的,对于函数原型的检查是在编译期执行的,链接时只需要VC链接器能找到main函数符号即可。


二、void替换int,有什么影响

有如下main函数

void main() {printf("Hello, world!\n"); }

 

其汇编代码如下:

printf("Hello, world!\n"); 00A4D70E mov esi,esp 00A4D710 push offset string "Hello, world!\n" (0A53894h) 00A4D715 call dword ptr [__imp__printf (0A586FCh)] 00A4D71B add esp,4 00A4D71E cmp esi,esp 00A4D720 call @ILT+1335(__RTC_CheckEsp) (0A4153Ch) } 00A4D725 xor eax,eax 00A4D727 pop edi 00A4D728 pop esi 00A4D729 pop ebx 00A4D72A add esp,0C0h 00A4D730 cmp ebp,esp 00A4D732 call @ILT+1335(__RTC_CheckEsp) (0A4153Ch) 00A4D737 mov esp,ebp 00A4D739 pop ebp 00A4D73A ret

编译器会补上xor eax,eax ,返回值放在eax中。

也就是说void替换int后,该函数返回值就是0,不能返回其它值了。其他代码使用GetExitCodeProcess()获取该进程的退出代码时,只能得到0,不具备指示意义。

 

转载于:https://www.cnblogs.com/shokey520/p/3673880.html

总结

以上是生活随笔为你收集整理的main函数声明的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。