对Linux GCC常用命令的简单解析以及应用

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、总结

以上的一些操作命令可以说是十分基础的东西,需要大家十分熟练的掌握。否则的话,边敲代码边找操作命令可是很痛苦的一件事情。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值