目录
1、程序准备
一个简单的C++源程序,程序名称为main.cpp
#include <iostream>
using namespace std;
int main()
{
cout << "Hello world!!" << endl;
return 0;
}
2、简单编译
① 最常用的代码:
g++ main.cpp -o main // 当源程序为c语言程序时,需要将g++改为gcc,下面皆是如此
实际上,上述的编译过程一共包括了四个步骤:预处理,编译、汇编和连接,接下来将对上述四个步骤进行更加详细的说明
② 四个步骤
(1)预处理:
预处理过程:
(1) 将所有的#define删除,并且展开所有的宏定义,并且处理所有的条件预编译指令,比如#if等
(2) 处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置
(3) 删除所有的注释 “//” 和 “/**/”
(4) 添加行号和文件标识,以便编译时产生调试用的行号以及编译错误警告行号
(5) 保留所有的#pragma编译器指令,后续编译过程需要使用它们
预处理指令:
g++ -E main.cpp -o main.i
main.i文件可以作为普通文本文件打开进行查看,其代码片段如下所示:
# 2 "main.cpp" 2
# 2 "main.cpp"
using namespace std;
int main()
{
cout << "Hello world!!" << endl;
return 0;
}
(2)编译
什么是编译?
编译过程就是对预处理玩的文件进行一系列的词法分析,语法分析,语义分析以及优化后生成对应的汇编代码。
进行编译的代码如下:
g++ -S main.i -o main.s
main.s也可以进行查看,其全部为汇编代码
(3)汇编
汇编过程调用对汇编代码进行处理,生成处理器能识别的指令,保存在后缀为.o的目标文件中。
汇编指令如下:
g++ -c main.s -o main.o
(4)链接
链接分为两类,为静态链接和动态链接:
(1). 静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。
(2). 动态链接则是只链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中吧响应动态库加入到内存中去。
使用命令 “g++ main.cpp -o main” 则会使用动态库进行链接,分别输入代码“size 文件名”和“ldd 文件名”可查看生成的ELF可执行文件大小和链接的动态库的情况,如下所示:
使用命令“g++ -static main.cpp -o main”则会使用静态库进行链接,ELF的可执行文件的大小和链接的动态库的情况,如下所示:
我们可以明显的看到静态库时,text的大小明显变的极大,而且查看链接情况时会显示“不是动态可执行文件”。
3、分析ELF文件(了解)
① ELF文件的段
一个典型的ELF文件包含下面几个段(section):
.text: 已编译程序的指令代码段
.rodata: ro代表read only,即只读数据
.data: 已初始化的C++程序全局变量和静态局部变量
.bss: 未初始化的C++程序全局变量和静态局部变量
.debug:调试符号表
我们可以使用指令“readelf -S”查看其各个段的信息,如下:
② 反汇编ELF
由于ELF文件无法被当做普通文本文件打开,如果希望直接查看一个ELF文件包含的指令和数据,需要使用反汇编的方法。
使用objdump -D对其进行反汇编的如下:
使用objdump -S 将其反汇编并且将其C语言源代码混合显示出来:(记得要加上g++ -o main -g main.cpp这行代码)
我们可以看到,已经进行了C++语言源程序的显示了
4、多文件的编译
① 代码准备
main.cpp
#include <iostream>
#include "function.h"
using namespace std;
int main()
{
greeting();
return 0;
}
function.cpp
#include <iostream>
using namespace std;
void greeting()
{
cout << "hello" << endl;
}
function.h
void greeting();
② 生成可执行文件:
一行代码:
g++ main.cpp function.cpp -o main
分步编译,大致可分为一下几步:
g++ -c main.cpp -o main.o
g++ -c function.cpp -o function.o
g++ main.o function.o -o main
③ 执行结果(直接执行,和分步执行)
两者的结果都是一样的,大家可以自己在虚拟机上进行试验
④ 小技巧
如果一个项目中有很多个源文件,那么我们可以偷个懒,使用以下代码进行操作,是一样的结果
g++ *.cpp -o main
5、总结
以上的一些操作命令可以说是十分基础的东西,需要大家十分熟练的掌握。否则的话,边敲代码边找操作命令可是很痛苦的一件事情。