首页 > main函数声明

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!
");
}

 

其汇编代码如下:

printf("Hello, world!
");
00A4D70E mov esi,esp 
00A4D710 push offset string "Hello, world!
" (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

更多相关:

  • 草色新雨中, 松声晚窗里。之前我们学习 Power Query 都是用鼠标就完成了很多复杂的操作。虽然 PowerQuery 已经将大部分常用功能内置成到功能区。基本能完成我们大部分的报表自动化功能。但是总有些复杂的或者个性化的问题是开发团队没有预先想到的,这时我们就需要学习 M 语言。一、M 语言在哪里?M语言的函数公式有三个地...

  • 前言从2020年3月份开始,计划写一系列文档--《小白从零开始学编程》,记录自己从0开始学习的一些东西。第一个系列:python,计划从安装、环境搭建、基本语法、到利用Django和Flask两个当前最热的web框架完成一个小的项目第二个系列:可能会选择Go语言,也可能会选择Vue.js。具体情况待定,拭目以待吧。。。基本概念表达式表...

  • 1.1函数1.1.1什么是函数函数就是程序实现模块化的基本单元,一般实现某一功能的集合。函数名:就相当于是程序代码集合的名称参数:就是函数运算时需要参与运算的值被称作为参数函数体:程序的某个功能,进行一系列的逻辑运算return 返回值:函数的返回值能表示函数的运行结果或运行状态。1.1.2函数的作用函数是组织好的,可重复使用的,用来...

  • 原标题:基于Python建立深度神经网络!你学会了嘛?图1 神经网络构造的例子(符号说明:上标[l]表示与第l层;上标(i)表示第i个例子;下标i表示矢量第i项)单层神经网络图2 单层神经网络示例神经元模型是先计算一个线性函数(z=Wx+b),接着再计算一个激活函数。一般来说,神经元模型的输出值是a=g(Wx+b),其中g是激活函数(...

  • 在学习MySQL的时候你会发现,它有非常多的函数,在学习的时候没有侧重。小编刚开始学习的时候也会有这个感觉。不过,经过一段时间的学习之后,小编发现尽管函数有很多,但是常用的却只有那几个。今天小编就把常用的函数汇总一下,为大家能够能好的学习MySQL中的函数。MySQL常使用的函数大概有四类。时间函数、数学函数、字符函数、控制函数。让我...

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...