你们知道计算机使用的一系列的1和0ios
那个一个C++语言程序又是如何从一个个.h和.cpp文件变成包含1和0的可执行文件呢?c++
能够认为有如下的几个环节编程
源程序->预处理->编译和优化->生成目标文件->连接->可执行文件windows
1.预处理函数
C++的预处理是指在C++程序源代码被编译以前,由预处理器对C++程序源代码进行的处理。这个过程并不对程序的源代码进行解析。优化
这里的预处理器(preprocessor)是指真正的编译开始以前由编译器调用的一个独立程序。this
预处理器主要负责如下的几处spa
1.宏的替换.net
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=100;
*在vs2013中可使用“VS2013 开发人员命令提示”
使用cl /P main.cpp只进行预编译生成main.i文件
*g++中可使用(在如下只使用g++进行演示)
g++ –E main.cpp>main.i命令
g++ –E a.cpp>main.i
打开生成的A.i文件
咱们发现
一、show函数中的注释已经被删掉了
二、main函数中的MACRO宏被替成了"this is a macro”
windows vs下
三、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