VC++ 编译过程

一 前言

一开始编译C++代码的时候可能会对编译的错误觉得很难理解,搞不清楚究竟是哪里错了。了解编译过程,能够更好的处理编译错误。

二 名词解释

编译单元:当一个c或cpp文件在编译时,预处理器首先递归包含头文件,形成一个含有所有 必要信息的单个源文件,这个源文件就是一个编译单元。

目标文件:目标文件包含着机器代码(可直接被计算机中央处理器执行)以及代码在运行时使用的数据,此外还包括其他调试信息。

三 编译过程

在VC中编译过程会分成以下三步:

1,预处理
2,生成目标文件
3,链接成可执行文件

 

1,预处理

将头文件加载进来,处理各种#define,如:宏,预编译条件,生成一个独立的编译单元。

可以通过以下的命令来生成独立的编译单元。

cl /EP test.cpp > test_p.cpp

这个命令的意思是,把源文件生成编译单元并写到test_p.cpp中。举个例子

下面是源文件代码

// test.cpp : Defines the entry point for the console application.

//



#include "stdafx.h"

#include <windows.h>

#include <iostream>



#define MAX(a,b)    (a>b?a:b)



#define PI    3.1415927



#ifdef UNICODE

typedef wchar_t MTCHAR;

#else

typedef char    MTCHAR;

#endif // UNICODE

int _tmain(int argc, _TCHAR* argv[])

{

    std::cout << MAX(10, 20) << std::endl;

    std::cout << PI << std::endl;

    MTCHAR *str = _T("hello world!");

    _tprintf(_T("%s\n"), str);

    return 0;

}

源代码中包含了三个头文件,定义一个表达式的宏,一个常量的宏,和使用预编译条件定义了一个字符类型

我们通过上面的命令生成新的文件,包含文件指令会把头文件引进来,把宏在代码中替换掉,把预编译条件指令处理。

/*

这里省略掉大量的头文件代码,整个文件总共有三十多万行。

*/



typedef char    MTCHAR;



int main(int argc, _TCHAR* argv[])

{

    std::cout << (10>20?10:20) << std::endl;

    std::cout << 3.1415927 << std::endl;

    MTCHAR *str = "hello world!";

    printf("%s\n", str);

    return 0;

}

也可以在cl命令中加入宏UNICODE和_UNICODE,这样可以更清晰地看到预处理条件指令的处理效果

cl /EP /D "UNICODE" /D "_UNICODE" test.cpp > test_p.cpp

生成的编译单元

/*

这里省略掉大量的头文件代码,整个文件总共有三十多万行。

*/



typedef wchar_t MTCHAR;



int wmain(int argc, _TCHAR* argv[])

{

    std::cout << (10>20?10:20) << std::endl;

    std::cout << 3.1415927 << std::endl;

    MTCHAR *str = L"hello world!";

    wprintf(L"%s\n", str);

    return 0;

}

MTCHAR已经被定义为wchar_t而不是char了,而且字符串也是wchar格式。

 

2,生成目标文件

将编译单元进行编译,生成目标文件(.obj文件)。这里通常分两个阶段:首先生成汇编语言,然后适用汇编生成机器码。

通过刚才生成的编译单元来生成目标文件

cl /c test_p.cpp

已经生成里机器码,所以不贴文件内容了。

3,链接

链接的任务就是把目标文件连起来生成可执行文件。

link test.obj

使用这个命令就能生成exe文件。

4,cl命令

cl命令有几个跟标准库有关的选项:/ML,/MLd,/MT,/MTd,/MD,/MDd。这些选项是想告诉编译器应用程序需要什么标准库。

/ML:(缺省选项)对应单线程静态的标准库。

/MT:对应多线程静态标准库 (libcmt.lib) ,此时编译器会自动定义 _MT 宏。

/MD:对应多线程 DLL 版 ( 导入库 msvcrt.lib , DLL 是msvcrt.dll) ,编译器自动定义 _MT 和 _DLL两个宏。
/MLd:对应调试单线程静态标准库 (libcd.lib) 。
/MTd:对应调试多线程静态标准库 (libcmtd.lib) 。
/MDd:对应调试多线程 DLL 标准库 ( 导入库msvcrtd.lib, DLL 是msvcrtd.dll) 。

你可能感兴趣的:(vc++)