一 基本概念
C运行时库给我们提供必要的库函数,如memcpy, printf, malloc等;它还提供的另外一个重要就是为应用程序添加启动函数。而C运行时库启动函数的主要功能为进行程序的初始化,对全局变量进行赋初始值,加载用户程序入口函数。
平时的所谓入口函数WinMain()右C run-time 库中的 void WinMainCRTStartup(void)函数调用,在默认情况下,这个才是真正的入口点函数(在不采用宽字符集的情况下)。可以在VC安装目录中的CRT/SRC/CRT0.c原代码文件中看到该函数定义。
在默认情况下,link程序连接了C 运行时库的某一个, 并且将函数mainCRTStartup(), wmainCRTStartup(), WinMainCRTStartup(), wWinMainCRTStartup()中的一个作为缺省的入口函数,可以根据link命令行中指定的子系统进行选择。
而自己的vc程序的入口点函数可以在编译器以便宜选项的方式指定,它可以使符合下面的形式的任何名称的函数:
void _cdecl EntryName(void) ;
二 mainCRTStartup() 函数分析
以下是经过别人简化后的入口函数代码。
#undef _UNCODE
void WinMainCRTStartup (void)
{
int mainret;
STARTUPINFO StartupInfo;
_osver = GetVersion ();
_winminor = (osver >>8) & 0x00FF;
_winmajor = _osver & 0x00FF;
_winver = (winmajor << 8) + _winminor;
osver = (osver >> 16) & 0x00FFFF;
if (!_heap_init (1))
fast_error_exit (_RT_HEAPINIT);
_acmdln = (char*) GetCommandLineA ();
_aenvptr = (char*) __crtGetEnvironmentStringsA ();
_setargv ();
_setenvp ();
_cinit ();
StartupInfo.dwFlags = 0;
GetStartupInfo (&StartupInfo);
mainret = WinMain (GetModuleHandleA (NULL),
NULL,
;pszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOWS ?
StartupInfo.wShowWindow : SW_SHOWDEFAULT);
exit (mainret);
}
运行时库在调用用户程序的main或者WinMain函数前,首先进行初始化工作。只有首先进行进行初始化工作,我们的C 运行时库和应用程序才能正确工作。其具体代码含义如下:
!获取操作系统的版本信息,用于以后操作
!进行初始化进程堆栈
!获取命令行,获取和设置环境变量
!C运行时内部变量初始化
! 调用标准win32入口函数
! 调用ExitProcess函数退出应用程序, 退出代码是WinMain的返回值
除了crt0.c, C运行时库还包含wcrt0.c, wincrt0.c , wwincrt0.c 三个文件用来提启动函数。 wcrt0.c是crt0.c的宽字符集版,wincrt0.c中包含windows应用程序的入口函数,而wwincrt0.c则是wincrt0.c的宽字符集版。
三 使用自定义函数代替C run-time中的启动函数
首先建立原代码文件init.c,在其中定义自己的启动函数 void entry (void)。代码如下所示:
#include<windows.h>
void entry (void)
{
char** p;
char* pAlloc ;
int i;
char * pszNames[]={
"master",
"Kai Ma",
"John",
"QQ",
NULL
} ;
p=pszNames;
for (i=0; p[i]!=NULL; i++)
{
MessageBox(NULL, p[i],"good",MB_OK) ;
}
}
编译程序:cl init.c /c
连接目标文件:link init.obj /SUBSYSTEM:WINDOWS /OUT: init.exe /ENTRY: "entry" /NODEFALUTLIB kernel32.lib user32.lib
这个程序使用了kernel32.lib user32.lib,但是在连接选项中指定了自己的入口函数,因此没有使用c 运行时库,也没有使用通常的入口函数 main /WinMain。 但是这个程序完全可以执行,是个标准的win32程序。
如果要在vc6集成环境中编译连接这个程序,需要的设置如下:在c/c++页下设置编译选项/nologo /c,其他选项都删除;在link标签下的文本框设置连接选项为:/SUBSYSTEM:WINDOWS /OUT: init.exe /ENTRY: "entry" /NODEFALUTLIB kernel32.lib user32.lib 。然后编译执行。