Chinese:
1、需要认识到main或者WinMain并不是真正的程序入口,它们也是函数,需要一个调用者。真正的入口一般为mainCRTStartup, wmainCRTStartup, WinMainCRTStartup或wWinMainCRTStartup,前两个是控制台环境下的多字节编码和Unicode编码的启动函数,后两个是Windows环境下多字节编码和Unicode编码的启动函数。
2、在启动函数中,有几个比较重要的默认启动函数
(1) GetVersion: 获取当前运行平台的版本号。
(2) _heap_init: 用于初始化堆空间。在函数实现中使用HeapCreate申请堆空间,申请空间的大小由_heap_init传递的参数决定。_sbh_heap_init函数用于初始化堆结构信息。
(3) GetCommandLineA: 获取命令行参数信息的首地址。
(4) _crtGetEnvironmentStringsA: 获取环境变量信息的首地址。
(5) _setargv: 根据GetCommandLineA获取命令行参数信息的首地址并进行参数分析,将分离出的参数的个数保存在全局变量_argc中,将分析出的每个命令行参数的首地址存放在数组中,并将这个字符指针数组的首地址保存在全局变量_argv中。
(6) _setenvp: 此函数根据_crtGetEnvironmentStringsA函数获取环境变量信息的首地址并进行分析,将得到的每条环境变量字符串的首地址存放在字符指针数组中,并将这个数组的首地址存放在全局变量env中。
(7) _cinit: 用于全局数据和浮点寄存器的初始化。全局对象和IO流等的初始化都是通过这个函数实现的。利用函数_initterm进行数据链初始化,这个函数由两个参数组成,类型为_PVFV *,这是一个函数指针数组,其中保留了每个初始化函数的地址。原型为:
typedef void (_cdec1 *_PVFV)(void);
C++规定全局对象和静态对象必须在main函数前构造,在main函数返回后析构。因此,这里的_PVFV函数指针数组就是用来代理调用构造函数的。
// _cinit函数代码片段 // 用于初始化寄存器 if (_FPinit != NULL) (*_FPinit)(); //初始化浮点寄存器 // 用于初始化C语法中的数据 _initterm(_xi_a, _xi_z); // 用于初始化C++语法中的数据 _initterm(_xc_a, _xc_z);