C-01\编译器和链接器以及真正的入口函数
编译器:
工具 | 编译器 | 路径 |
---|---|---|
VC++6.0 |
CL.EXE (一段shell)只负责分析命令行参数,真正功能实现在C1.DLL、C1XX.DLL、C2.DLL |
C:\Program Files (x86)\Microsoft Visual Studio\VC98\Bin |
VS2019 |
CL.EXE (一段shell),真正功能实现在C1.DLL、C1XX.DLL、C2.DLL |
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\Hostx64\x64 |
链接器:
工具 | 链接器 | 路径 |
---|---|---|
VC++6.0 |
LINK.EXE |
C:\Program Files (x86)\Microsoft Visual Studio\VC98\Bin |
VS2019 |
LINK.EXE |
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\Hostx64\x64 |
VC++6.0
: 6.0说的是链接器的版本,不是编译器的版本
注意:vs2019
正版会在线更新编译器
在所在目录右键快速打开cmd
设置方法(WIN 10
):
1.右键:命令行
[HKEY_CLASSES_ROOT\Directory\Background\shell\OpenCmdHere]
@="在此处打开命令行窗口"
[HKEY_CLASSES_ROOT\Directory\Background\shell\OpenCmdHere\command]
@="cmd.exe -noexit -command Set-Location -literalPath \"%V\""
2.右键:命令行(管理员)
[HKEY_CLASSES_ROOT\Directory\Background\shell\runas]
@="在此处打开命令行窗口(管理员)"
"ShowBasedOnVelocityId"=dword:00639bc8
[HKEY_CLASSES_ROOT\Directory\Background\shell\runas\command]
@="cmd.exe /s /k pushd \"%V\""
编译器常用参数:
/c 只编译不链接 生成 .obj文件(.obj标准为coff标准,可以跨语言平台,其余语言也可以使用)
/W 警告等级,分1~4级,4级最高,默认为1级(/W1~/W4),/W3 不会报变量闲置警告,/W4会报变量闲置警告
/WX 将警告视为错误,一旦有了警告,动作停止,不产生.obj文件,迫使操作员对警告进行处理
/P 生成预处理信息文件 .i(带#的语句都是预处理语句) 可以查看复杂宏的正确性
编译和链接的指令:
编译指令:
cl /c filePath //filePath为要编译的文件路径
链接指令:
link filePath //filePath为要链接的文件路径
#include <> 与#include ""区别:
#include <> // 先根据每个 /I 编译器选项指定的路径查找,然后再根据环境变量 include 命令设置的路径去找
// 然后copy整个文件替换该语句
#include "" // 如果文件名给定的是全路径,则只搜索该路径
// 如果是相对路径,则先在源文件所在的目录查找,然后根据每个 /I 编译器选项指定的路径查找,最后再根据环境变量 include 命令设置的路径去找
// 然后copy整个文件替换该语句
include 不检查扩展名
入口函数所在文件路径:
C:\Program Files (x86)\Microsoft Visual Studio\VC98\CRT\SRC\CRT0.C //VC++6.0
/***
*BaseProcessStartup(PVOID Peb)
*
*Purpose:
* This routine does the C runtime initialization, calls main(), and
* then exits. It never returns.
*
*Entry:
* PVOID Peb - pointer to Win32 Process Environment Block (not used)
* //
*Exit:
* This function never returns. // 该函数没有返回值
*
*******************************************************************************/
// 通过宏 _WINMAIN_ 区分窗口和控制台 存在宏 _WINMAIN_ 就是窗口程序
// 通过宏 WPRFLAG 区分宽字节和多字节 存在宏 WPRFLAG 就是宽字节
// 通过宏 _MT 区分多线程还是单线程
// 窗口宽字节
void wWinMainCRTStartup(void)
{
int mainret; // 主函数返回值
_TUCHAR *lpszCommandLine;
STARTUPINFO StartupInfo;
/*
* Get the full Win32 version
*/
_osver = GetVersion(); // 获取系统版本
// 分离系统版本号
_winminor = (_osver >> 8) & 0x00FF ;
_winmajor = _osver & 0x00FF ;
_winver = (_winmajor << 8) + _winminor;
_osver = (_osver >> 16) & 0x00FFFF ;
#ifdef _MT
if ( !_heap_init(1) ) /* initialize heap */ // 多线程情况下初始化堆
#else /* _MT */
if ( !_heap_init(0) ) /* initialize heap */ // 单线程情况下初始化堆
#endif /* _MT */
fast_error_exit(_RT_HEAPINIT); /* write message and die */
#ifdef _MT
if( !_mtinit() ) /* initialize multi-thread */ // 多线程情况下初始化多线程环境
fast_error_exit(_RT_THREAD); /* write message and die */
#endif /* _MT */
/*
* Guard the remainder of the initialization code and the call
* to user's main, or WinMain, function in a __try/__except
* statement.
*/
__try {
_ioinit(); /* initialize lowio */ // 初始化io
/* get wide cmd line info */
_wcmdln = (wchar_t *)__crtGetCommandLineW(); // 获取命令行信息
/* get wide environ info */
_wenvptr = (wchar_t *)__crtGetEnvironmentStringsW(); // 获取环境变量信息
_wsetargv(); // 格式化命令行信息
_wsetenvp(); // 格式化环境变量信息
// 全局数据初始化和静态数据初始化以及C++全局对象的构造函数的调用
_cinit(); /* do C data initialize */
StartupInfo.dwFlags = 0;
GetStartupInfo( &StartupInfo ); // 获取当前进程的基本环境
lpszCommandLine = _wwincmdln(); // 获取命令行参数
mainret = wWinMain(
GetModuleHandleA(NULL),
NULL,
lpszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOW
? StartupInfo.wShowWindow
: SW_SHOWDEFAULT
);
exit(mainret); // 退出进程,里面调用 ExitProcess(mainret),同时处理全局对象的释放工作
}
__except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
{
/*
* Should never reach here
*/
_exit( GetExceptionCode() );
} /* end of try - except */
}
// 窗口多字节
void WinMainCRTStartup(void)
{
int mainret;
_TUCHAR *lpszCommandLine;
STARTUPINFO StartupInfo;
/*
* Get the full Win32 version
*/
_osver = GetVersion();
_winminor = (_osver >> 8) & 0x00FF ;
_winmajor = _osver & 0x00FF ;
_winver = (_winmajor << 8) + _winminor;
_osver = (_osver >> 16) & 0x00FFFF ;
#ifdef _MT
if ( !_heap_init(1) ) /* initialize heap */
#else /* _MT */
if ( !_heap_init(0) ) /* initialize heap */
#endif /* _MT */
fast_error_exit(_RT_HEAPINIT); /* write message and die */
#ifdef _MT
if( !_mtinit() ) /* initialize multi-thread */
fast_error_exit(_RT_THREAD); /* write message and die */
#endif /* _MT */
/*
* Guard the remainder of the initialization code and the call
* to user's main, or WinMain, function in a __try/__except
* statement.
*/
__try {
_ioinit(); /* initialize lowio */
/* get cmd line info */
_acmdln = (char *)GetCommandLineA();
/* get environ info */
_aenvptr = (char *)__crtGetEnvironmentStringsA();
_setargv();
_setenvp();
_cinit(); /* do C data initialize */
StartupInfo.dwFlags = 0;
GetStartupInfo( &StartupInfo );
lpszCommandLine = _wincmdln();
mainret = WinMain(
GetModuleHandleA(NULL),
NULL,
lpszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOW
? StartupInfo.wShowWindow
: SW_SHOWDEFAULT
);
exit(mainret);
}
__except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
{
/*
* Should never reach here
*/
_exit( GetExceptionCode() );
} /* end of try - except */
}
// 控制台宽字节
void wmainCRTStartup(void)
{
int mainret;
/*
* Get the full Win32 version
*/
_osver = GetVersion();
_winminor = (_osver >> 8) & 0x00FF ;
_winmajor = _osver & 0x00FF ;
_winver = (_winmajor << 8) + _winminor;
_osver = (_osver >> 16) & 0x00FFFF ;
#ifdef _MT
if ( !_heap_init(1) ) /* initialize heap */
#else /* _MT */
if ( !_heap_init(0) ) /* initialize heap */
#endif /* _MT */
fast_error_exit(_RT_HEAPINIT); /* write message and die */
#ifdef _MT
if( !_mtinit() ) /* initialize multi-thread */
fast_error_exit(_RT_THREAD); /* write message and die */
#endif /* _MT */
/*
* Guard the remainder of the initialization code and the call
* to user's main, or WinMain, function in a __try/__except
* statement.
*/
__try {
_ioinit(); /* initialize lowio */
/* get wide cmd line info */
_wcmdln = (wchar_t *)__crtGetCommandLineW();
/* get wide environ info */
_wenvptr = (wchar_t *)__crtGetEnvironmentStringsW();
_wsetargv();
_wsetenvp();
_cinit(); /* do C data initialize */
__winitenv = _wenviron;
mainret = wmain(__argc, __wargv, _wenviron);
exit(mainret);
}
__except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
{
/*
* Should never reach here
*/
_exit( GetExceptionCode() );
} /* end of try - except */
}
// 控制台多字节
void mainCRTStartup(void);
{
int mainret;
/*
* Get the full Win32 version
*/
_osver = GetVersion();
_winminor = (_osver >> 8) & 0x00FF ;
_winmajor = _osver & 0x00FF ;
_winver = (_winmajor << 8) + _winminor;
_osver = (_osver >> 16) & 0x00FFFF ;
#ifdef _MT
if ( !_heap_init(1) ) /* initialize heap */
#else /* _MT */
if ( !_heap_init(0) ) /* initialize heap */
#endif /* _MT */
fast_error_exit(_RT_HEAPINIT); /* write message and die */
#ifdef _MT
if( !_mtinit() ) /* initialize multi-thread */
fast_error_exit(_RT_THREAD); /* write message and die */
#endif /* _MT */
/*
* Guard the remainder of the initialization code and the call
* to user's main, or WinMain, function in a __try/__except
* statement.
*/
__try {
_ioinit(); /* initialize lowio */
/* get cmd line info */
_acmdln = (char *)GetCommandLineA();
/* get environ info */
_aenvptr = (char *)__crtGetEnvironmentStringsA();
_setargv();
_setenvp();
_cinit(); /* do C data initialize */
__initenv = _environ;
mainret = main(__argc, __argv, _environ);
exit(mainret);
}
__except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
{
/*
* Should never reach here
*/
_exit( GetExceptionCode() );
} /* end of try - except */
}
补充知识
vs
中8字节的是__int64
,long int
还是4字节,可能为了用户黏性,故意为之,与c标准不一致- 常量后面加
L
,表示长整型常量,占8字节 - 3.14是双精度浮点数,加
f
才是单精度浮点数 stdin, stdout
支持重定向stderr
不支持重定向