一 前言

一开始编译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. Spring Boot的启动器Starter详解

    Spring Boot的启动器Starter详解 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs Spring Boot ...

  2. [Leetcode][Python]22: Generate Parentheses

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 22: Generate Parentheseshttps://oj.leet ...

  3. 剑指offer 25 二叉树中和为某一值的路径

    非递归方法: class Solution { public: vector<vector<int>> FindPath(TreeNode* root,int expectNu ...

  4. Extjs 4 生成饼状图的例子

    前台: //远程抄表设备下落图表数据 var Store1 = new Ext.data.Store({ <span style="white-space:pre"> ...

  5. 每个页面的Title样式

    <style>.zc_lan14 {}{    TEXT-ALIGN: center; FONT-FAMILY: "微软雅黑"; MARGIN-BOTTOM: 3px; ...

  6. ServiceStack 入门(二)

    本文介绍创建一个简单的基于ServiceStack的项目. 1. 新建一个solution 2.创建完成后有4个project. ServiceModel是定义Request DTO 和 Reques ...

  7. oracle 使用 decode函数 或 case when 实现行转列

    ----创建测试表 create table student_score( name varchar2(20), subject varchar2(20), score number(4,1) ); ...

  8. JavaSE复习日记 : 抽象类

    /* * 抽象类 * 抽象: * 面向对象的三大核心思想; * 封装: 封装,ppp是封装的一部分 * 继承; * 多态: 父类的引用指向子类的对象 * 引用: 是指一个引用型变量 * 有哪些变量? ...

  9. 笔记-AndroidStudio开发环境的搭建

    首先当然是下载AndroidStudio,目前最新的稳定版是1.1 然后下载studio版本的sdk,如果用原装sdk,需要更新   安装的过程中会选择sdk的路径,此时如果已经解压了原装sdk,会进 ...

  10. intellj idea 如何设置类头注释和方法注释

    intellj idea 如何设置类头注释和方法注释           intellj idea的强大之处就不多说了,相信每个用过它的人都会体会到,但是我们也会被他的复杂搞的晕头转向,尤其刚从ecl ...