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字节的是__int64long int还是4字节,可能为了用户黏性,故意为之,与c标准不一致
  • 常量后面加L,表示长整型常量,占8字节
  • 3.14是双精度浮点数,加f才是单精度浮点数
  • stdin, stdout支持重定向
  • stderr不支持重定向
posted @ 2022-02-09 16:07  逸聆君  阅读(284)  评论(0编辑  收藏  举报