一 前言

一开始编译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(, ) << std::endl;
std::cout << PI << std::endl;
MTCHAR *str = _T("hello world!");
_tprintf(_T("%s\n"), str);
return ;
}

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

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

/*
这里省略掉大量的头文件代码,整个文件总共有三十多万行。
*/ typedef char MTCHAR; int main(int argc, _TCHAR* argv[])
{
std::cout << (>?:) << std::endl;
std::cout << 3.1415927 << std::endl;
MTCHAR *str = "hello world!";
printf("%s\n", str);
return ;
}

也可以在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 << (>?:) << std::endl;
std::cout << 3.1415927 << std::endl;
MTCHAR *str = L"hello world!";
wprintf(L"%s\n", str);
return ;
}

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++ 编译过程的更多相关文章

  1. Qt打开外部程序和文件夹需要注意的细节(Qt调用VC写的动态库,VC需要用C的方式输出函数,否则MinGW32编译过程会报错)

    下午写程序中遇到几个小细节,需要在这里记录一下. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 QProcess *process = new QProcess(this ...

  2. 3DSlicer源代码编译过程vs2008+windows xp [转]

    一 下载QT源代码编译 1.  简述   在 Windows2000/xp/vista 下,安装 VS2008, QT 4.7.2 :并在 VS2008上建立 QT 的集成开发环境,利用 VS2008 ...

  3. VC编译连接选项详解

    VC编译连接选项详解 大家可能一直在用VC开发软件,但是对于这个编译器却未必很了解.原因是多方面的.大多数情况下,我们只停留在“使用”它,而不会想去“了解”它.因为它只是一个工具,我们宁可把更多的精力 ...

  4. VC++ 编译libcurl 支持SSL,GZIP

    由于网上下载的 libcurl 不支持 gzip,只好自己动手编译,期间走了很多弯路,下面是最终成功的记录. 我所使用的环境 Visual Studio 2010 . Windows 7 64 bit ...

  5. C/C++编译过程

    C/C++编译过程 C/C++编译过程主要分为4个过程 1) 编译预处理 2) 编译.优化阶段 3) 汇编过程 4) 链接程序 一.编译预处理 (1)宏定义指令,如#define Name Token ...

  6. VC编译那些事儿

    转载自:http://blog.csdn.net/wowolook/article/details/8077153     最近又被ms的编译选译纠结了一下,运行程序是老是弹出0x14b1 or 71 ...

  7. win10--vs2015--libjpeg--64位库的编译过程记录

    win10--vs2015--libjpeg--64位库的编译过程记录 1. 下载源代码:   http://libjpeg.sourceforge.net/    或者  http://www.ij ...

  8. VC++编译说明

    目录 第1章编译步骤    1 第2章编译源文件    2 2.1 编译器    2 2.2 包含头文件    3 2.3 重复包含    6 2.4 预编译头文件    7 2.4.1 创建     ...

  9. VC++ 编译libcurl 支持SSL,GZIP(有脚本)

    由于网上下载的 libcurl 不支持 gzip,只好自己动手编译,期间走了很多弯路,下面是最终成功的记录. 我所使用的环境 Visual Studio 2010 . Windows 7 64 bit ...

随机推荐

  1. silverlight datagrid绑定匿名类

    原文 http://www.cnblogs.com/luweis/archive/2011/10/21/2220587.html 刚开始遇到的一个问题是这样的,我有一个datagrid,根据不同的条件 ...

  2. WIN7 64位通过VPN远程登录 ASP.Net通过VPN访问Oracle服务器

    因为客户这边的服务器是64位的,所以本人手贱,把系统换成了64位的win7,以为来客户这边工作会更方便,谁知道来到客户这边,进不了他们公司的内网,然后给我一个VPN的账号,先VPN然后才能登录他们的测 ...

  3. 如何获取浏览器的DNS解析时间

    上一篇博客提到09年初WED团队开发的浏览器环境检测工具时,忘记说这个是aoao同学的创意了.不过没关系,据说他又在秘密规划新版本了,再据说新版要增加的DNS解析时间计算已经开发完成,点上面那个链接就 ...

  4. iOS 4.2 SDK安装

    iOS 4.2 SDK安装 ◆系统版本:10.6.5 ◆硬件配置: ◆10G空间,3.5G内存,显卡:GMA950 Xcode 3.2.5和iOS 4.2 SDK下载:http://developer ...

  5. 执行startx后Ubuntupassword正确进不去的问题

    今天在命令行里敲了 startx ,然后系统重新启动.输入password后,跳转到一下界面.之后又返回到登陆界面.一直这样循环输入password.进不去系统. 然后不得不用手机在网上查找解决的方法 ...

  6. JavaScript继承的实现

    怎样在JavaScript中实现简单的继承?  以下的样例将创建一个雇员类Employee,它从Person继承了原型prototype中的全部属性. function Employee(name, ...

  7. SQL学习之用通配符进行数据过滤

    一.Like操作符 之前介绍的所有的操作符都是针对已知值进行过滤.不管匹配一个值还是多个值,检验大于还是小于已知值,或者检查某个范围的值,其共同点是过滤中使用的值都是已知的. 但是这种方法并不是任何时 ...

  8. C# 轮循回调

    class Program { static void Main(string[] args) { Func<int> func = new Func<int>(GetInt) ...

  9. iphone/ipad前端开发技巧

    iPad开发的局限性 在iPad上使用Safari浏览普通网站网页的时候,网页因为太大而导致需要手动放大缩小或者滑动,虽然这种滑动行为在iPad上市之初的各种宣传中被津津乐道,但时间久了我们还是会发现 ...

  10. 如何升级CentOS 6.5下的MySQL

    如何升级CentOS 6.5下的MySQL http://jingyan.baidu.com/article/48a42057e9b9bca9242504ab.html | 浏览:1136 | 更新: ...