C/C++程序编译的四个过程
g++是Linux下C++的编译器;我为什么会选择Linux下的g++编译器,就是因为g++可以看到程序从编译到运行的过程做了些什么。而VS等集成开发环境看不到这些,并不是说VS工具不好,(VS还是相当好用的...)。对于学习来说,需要知道程序从编译到运行进行了哪些工作,做了哪些事情,首推g++编译器(这个看个人习惯)。
一、常见文件后缀
.c为后缀的文件:c语言源代码文件
.a为后缀的文件:是由目标文件构成的库文件
.cpp为后缀的文件:是c++源代码文件
.h为后缀的文件:头文件
.o为后缀的文件:是编译后的目标文件
.s为后缀的文件:是汇编语言源代码文件
.m为后缀的文件:Objective-C原始程序
.so为后缀的文件:编译后的动态库文件
二、g++执行的四个过程
1、预处理:条件编译,头文件包含,宏替换的处理,生成.i文件。
2、编译:将预处理后的文件转换成汇编语言,生成.s文件
3、汇编:汇编变为目标代码(机器代码)生成.o的文件
4、链接:连接目标代码,生成可执行程序
三、最简单的C++程序——"helloworld!\n"
-
// 新建hello.cpp文件,vim编辑
-
#include <iostream>
-
using namespace std;
-
int main(void)
-
{
-
count << "hello world!"<< endl;
-
reutrn 0;
-
}
(1)预处理阶段
g++ -E hello.cpp > hello.i
通过vim打开hello.i文件,你会发现一些情况(最好是自己观察,看看哪些内容被换了);
宏的替换,还有注释的消除,还有找到相关的库文件,将#include文件的全部内容插入。若用<>括起文件则在系统的INCLUDE目录中寻找文件,若用""括起文件则在当前目录中寻找文件。
用编辑器打开hello.i会发现有很多很多代码,你只需要看最后部分就会发现,预处理做了宏的替换,还有注释的消除,可以理解为无关代码的清除。
(2)编译
g++ -S hello.cpp
生成hello.s文件,.s文件表示是汇编文件,用编辑器打开就都是汇编指令。(可以通过vim编辑器看看hello.s里面的内容【都是汇编指令,哈哈】)。
(3)汇编
g++ -c hello.cpp
汇编变为目标代码(机器代码)生成.o的文件,.o是gcc生成的目标文件,用编辑器打开就都是二进制机器码。
(4)链接 ——链接生成可执行文件(库文件进行链接)
g++ -o hello hello.cpp
程序运行:./hello【输出hello world!】
在成功编译之后,就进入了链接阶段。在这里涉及到一个重要的概念:函数库(可以这么理解就是不带main()函数的.cpp生成的)。
可以重新查看这个小程序,在这个程序中并没有定义”cout”的函数(准确说cout不是函数,cout却很独特:既不是函数,似乎也不是C++特别规定出来的像if,for一类有特殊语法的“语句”,其实说到底还是函数调用,不过这函数有些特殊,用的是运算符重载,确切地说是重载了“<<”运算符。这里如果用pritf()函数说明会更好,暂且当做函数理解吧)实现,且在预编译中包含进的”iostream”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现”cout”函数的呢?系统把这些函数实现都被做到名为stdc++的库文件中去了,在没有特别指定时,g++会到系统默认的搜索路径”/usr/lib”下进行查找,也就是链接到stdc++库函数中去,这样就能实现函数”cout”了,而这也就是链接的作用。