C++编译与链接(1)-编译与链接过程
大家知道计算机使用的一系列的1和0
那个一个C++语言程序又是如何从一个个.h和.cpp文件变成包含1和0的可执行文件呢?
可以认为有以下的几个环节
源程序->预处理->编译和优化->生成目标文件->链接->可执行文件
1.预处理
C++的预处理是指在C++程序源代码被编译之前,由预处理器对C++程序源代码进行的处理。这个过程并不对程序的源代码进行解析。
这里的预处理器(preprocessor)是指真正的编译开始之前由编译器调用的一个独立程序。
预处理器主要负责以下的几处
1.宏的替换
2.删除注释
3.处理预处理指令,如#include,#ifdef
如我们有以下代码
temp.h
#ifndef _HEADERNAME_H
#define _HEADERNAME_H 1 #include <iostream>
inline void show(char *a)
{
std::cout << a<< std::endl;//annotation
} #endif
main.cpp
#include "temp.h"
#define MACRO "This is a macro" extern int i;
int main()
{
std::cout<<i<<std::endl;
show(MACRO);
}
a.cpp
#include <iostream>
int i=;
*在vs2013中可以使用“VS2013 开发人员命令提示”

使用cl /P main.cpp只进行预编译生成main.i文件
*g++中可以使用(在以下只使用g++进行演示)
g++ –E main.cpp>main.i命令
g++ –E a.cpp>main.i
打开生成的A.i文件
我们发现
1、show函数中的注释已经被删掉了

2、main函数中的MACRO宏被替成了"this is a macro”
windows vs下

3、temp.h和main.cpp中的#include<iostream> 和#include “temp.h”也在相应位置被展开了

2.编译和优化

词法分析 -- 识别单词,确认词类;比如int i;知道int是一个类型,i是一个关键字以及判断i的名字是否合法
语法分析 -- 识别短语和句型的语法属性;
语义分析 -- 确认单词、短语和句型的语义特征;
代码优化 -- 修辞、文本编辑;
代码生成 -- 生成译文。
内联函数的替换就发生在这一阶段
在g++中可以使用
g++ -S将预处理阶段生成的.i文件生成相应的汇编文件
g++ –S main.i main.s
g++ –S a.i a.s
生成的部分代码如下:

3.生成目标文件
汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。
在最终的目标文件中
除了拥有自己的数据和二进制代码之外,还要至少提供2个表:未解决符号表和导出符号表,分别告诉链接器自己需要什么和能够提供什么。
编译器把一个cpp编译为目标文件的时候,除了要在目标文件里写入cpp里包含的数据和代码,还要至少提供3个表:未解决符号表,导出符号表和地址重定向表。
未解决符号表提供了所有在该编译单元里引用但是定义并不在本编译单元里的符号及其出现的地址。
导出符号表提供了本编译单元具有定义,并且愿意提供给其他编译单元使用的符号及其地址。
地址重定向表提供了本编译单元所有对自身地址的引用的记录。
g++中可以使用g++ -c命令
g++ –c main.s –o main.o
g++ –c a.s –o a.o
4.链接
由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。
g++ a.o main.o –o main.out
最终运行结果如下
100
This is a macro
参考文献
C/C++程序从编译到最终生成可执行文件的过程分析 http://blog.csdn.net/wyb19890515/article/details/7211006
c/c++程序编译连接过程 http://blog.csdn.net/hitprince/article/details/7880241
C++编译与链接(1)-编译与链接过程的更多相关文章
- C/C++程序编译流程(预处理->编译->汇编->链接)
程序的基本流程如图: 1. 预处理 预处理相当于根据预处理指令组装新的C/C++程序.经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内 ...
- GCC编译器原理(三)------编译原理三:编译过程(3)---编译之汇编以及静态链接【2】
4.1.2 符号解析与重定位 (1)重定位 在完成空间和地址的分配步骤之后,链接器就进入了符号解析和重定位的步骤,这是静态链接的核心部分. 先看看 a.o 的反汇编文件: objdump -d a.o ...
- 使用MinGW编译Boost,MSVC编译Boost的几种链接方式 good
1.下载Boost(http://www.boost.org) 我目前用的是1.61.0版本 2.将MinGW下的bin目录完整路径设置到系统环境变量Path中,保证cmd命令行能找到gcc,g++等 ...
- GO 使用静态链接库编译 生成可执行文件 使用第三方 .a 文件,无源码构造
go build 和 go install 都需要使用源码来进行编译.但是有时候我们只有.a或者.so文件.并不能获取到第三方库的源码,这时我们需要静态链接库编译的技巧: 上图是实验前的文件分布. 使 ...
- linux下C/C++编译时系统搜索 include 和 链接库 文件路径的指定
C/C++程序在linux下被编译和连接时,GCC/G++会查找系统默认的include和link的路径,以及自己在编译命令中指定的路径.自己指定的路径就不说了,这里说明一下系统自动搜索的路径. ...
- C++ 多文件编译简述:头文件、链接性、声明与定义
目录 Commen Sense 头文件 链接性 static 与链接性控制 extern 与外部链接性 Reference Commen Sense C++ 在编译时对每个翻译单元(Translati ...
- CentOS下编译Lua使得其支持动态链接
在Linux下编译Lua时,我一般都是使用的make generic,这样编译没有什么问题,运行lua的程序也都OK,但是,这样在加载外部的C动态 链接库,却总是报下面的错误 dynamic libr ...
- 【嵌入式开发】gcc 学习笔记(一) - 编译C程序 及 编译过程
一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...
- [转]静态库、动态库,dll文件、lib文件,隐式链接、显式链接
转自:https://blog.csdn.net/dcrmg/article/details/53427181 静态链接.动态链接 静态库和动态库分别应用在静态链接方式和动态链接方式中,所谓静态链接方 ...
- nginx 编译安装时的编译参数说明(不建议看)
https://www.cnblogs.com/wazy/p/8108824.html ./configure --user=www \ #worker进程运行用户 --group=www \ #wo ...
随机推荐
- 用uliweb 创建项目
创建项目 ***@Android:~# uliweb makeproject ablog ***@Android:~# cd ablog/ ***@Android:~/ablog# ls apps f ...
- 20155220 吴思其 《网络攻防》 Exp1 PC平台逆向破解(5)M
20155220 <网络攻防> Exp1 PC平台逆向破解(5)M 实践内容 通过对实践对象--20155220pwn1的linux可执行文件的修改或输入,完成以下三块: 手工修改可执行文 ...
- 400 bad Request: JackSon将json串转成List<Object>,异常com.fasterxml.jackson.databind.JsonMappingException
最近遇到的400, 以前总以为 400 就是参数不匹配造成的,直到今天遇到这个问题 控制台报错如下: com.fasterxml.jackson.databind.JsonMappingExcept ...
- CLR via C#读书笔记一:CLR的执行模型
CLR(Common Language Runtime)公共语言进行时是一个可由多种编程语言使用的“进行时”. 将源代码编译成托管模块 可用支持CLR的任何语言创建源代码文件,然后用对应的编译器检查语 ...
- [JOISC2018]道路建设 LCT
[JOISC2018]道路建设 LOJ传送门 考的时候打的大暴力,其实想到了LCT,但是思路有点没转过来.就算想到了估计也不能切,我没有在考场写LCT的自信... 其实这题不是让你直接用LCT维护答案 ...
- 如何在ajax请求中设置特殊的RequestHeader
现在ajax应用已经相当广泛了,有很多不错的ajax框架可供使用.ajax是一个异步请求,也主要是一种客户端的脚本行为.那么,如何在请求之前为请求添加特殊的一些头部信息呢? 下面是一个简单的例子,我用 ...
- Linux之服务器介绍
服务器,也称伺服器,是提供计算服务的设备.由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力. 服务器: 服务器指的是网络中能对其他机器提供某些服务的计算机系统 ...
- git 自己易忘的命令
1. git 更新远程分支列表 git remote update origin --prune git remote update origin -p 2. 查看远程分支: git branch - ...
- 原生android(一)
一.移动APP的几种类型 1.Native APP:基于智能手机操作系统,并使用原生程序编写运行的应用程序,有IOS,Android,Windows Phone8等系统 2.Web APP:运行在智能 ...
- 0.0 配置JAVA环境和Maven环境(W10注意点)
今天上班第一天,真有些忘了之前配置的环境问题,全新的电脑开始配置. 电脑软件JDK以及eclipse都是下载最新的 添加最全的链接吧: 1.JDK配置链接:http://www.cnblogs.com ...