『Linux从入门到精通』第 ⑦ 期 - Linux编译器——gcc/g++(预处理、编译、汇编、链接)

简介: 『Linux从入门到精通』第 ⑦ 期 - Linux编译器——gcc/g++(预处理、编译、汇编、链接)

0000000000000.png

目录


程序实现的两大环境

gcc如何完成

预处理

编译

汇编

链接

动态库与静态库

对比二者生成的文件大小

gcc常用选项


文章导读


本章主要内容有认识与学习Linux环境下常用的编译器——gcc(编译C代码)/g++(编译C++代码)的常用指令等、程序实现的两大环境、动态库与静态库的理解等。


正文


程序实现的两大环境


任何一个C程序的实现都要经过翻译环境与执行环境。


在翻译环境中又分为4个部分,预编译、编译、汇编与链接。在各个阶段主要完成的任务有:


1.预编译(预处理):头文件的包含、注释的删除、#define符号的替换;


2.编译:将C语言代码转化为汇编代码;


3.汇编:把汇编指令转化为二进制指令;


4.链接:合并符号表和段表,生成可执行程序。

91.png


gcc如何完成


通过gcc指令的不同选项可查看各阶段所形成的文件;

格式:gcc  [选项] [目标文件名] -o [生成文件名]

首先在Test.c文件中写好C代码:

//Test.c
#include<stdio.h>
#define N 100
//这是一段注释.....
int main()
{
  int n = 0;
  printf("Hello World\n");
  printf("%d\n", n + N);
  return 0;
}


预处理


查看 Test.c 预处理后的结果,-E选项的作用是让 gcc 在预处理结束后停止编译过程;-o 的作用是将预处理后的内容保存到 test.i 文件中。

gcc -E Test.c -o test.i

7.png

如图所示,预处理阶段进行了头文件包含、注释的删除、#define的替换。


编译


接下来将刚刚生成的 test.i 进行编译,并在编译之后停下来,将结果写入 test.s 中。gcc所用选项为 -S。

gcc -S test.i -o test.s

6.png

我们虽然可能没学习过汇编语言,但依旧隐约认识到这些就是汇编代码;可见编译阶段就是将C代码翻译为汇编指令。


汇编


gcc所用选项为 -c;-o 将结果写入到 test.o 中。

gcc -c test.s -o test.o

11.png

正如我们所见,汇编完成之后都这这样的乱码。其实汇编之后,生成的文件为二进制文件,是用来给计算机看的,咱们已经看不懂了。


链接


编译完成之后就进入了链接阶段,链接完成之后就会生成可执程序 Test了。

gcc test.o -o Test

12.png

但是关于链接,我们需要知道它在链接什么。


我们是否好奇过为什么我们明明没有定义过函数 printf 、return .....等等的函数,但却可以使用它的功能?


其实,系统把这些函数的实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函 数 printf 了,而这也就是链接的作用。


动态库与静态库


函数库一般分为动、静态库两种。二者的区别可以理解为私有与公共的区别。就好比我们需要读一本《C和指针》,有两种方法可以选。一种是自己买一本,只有自己可以用,用起来还挺方便,缺点就是得花钱;第二种是去图书馆借书,图书馆的资源被所有人共享。


gcc 进行函数库的链接时可选择静态链接或者动态链接。


静态链接就类似于自己买书看,只给自己看同时还费钱(浪费内存),静态链接时会将库文件的代码全部加入到可执行文件中,因此生成的文件比较大。


动态链接类似于去图书馆借书。函数库就放在某个固定的地方,哪个程序想去使用就去自己去加载它。


Linux下gcc默认使用动态链接。


对比二者生成的文件大小


//采用静态链接
gcc -static Test.c -o Test_static
//默认采用动态链接
gcc  Test.c -o Test

若在静态链接时出错,可能是因为你的 Linux 没有安装C语言的静态库,须手动安装。

//安装C语言静态库
yum install -y glibc-static

两种连接方式生成的文件大小几乎相差百倍。


gcc常用选项


以下是gcc编译器常用选项汇总


-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面;

-S 编译到汇编语言不进行汇编和链接;

-c 编译到目标代码;

-o 文件输出到 文件;

-static 此选项对生成的文件采用静态链接;

-g 生成调试信息。GNU 调试器可利用该信息;

-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.;

-O0

-O1

-O2

-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高;

-w 不生成任何警告信息;

-Wall 生成所有警告信息。


目录
相关文章
|
28天前
|
自然语言处理 编译器 C语言
为什么C/C++编译腰要先完成汇编
C/C++ 编译过程中先生成汇编语言是历史、技术和实践的共同选择。历史上,汇编语言作为成熟的中间表示方式,简化了工具链;技术上,分阶段编译更高效,汇编便于调试和移植;实践中,保留汇编阶段降低了复杂度,增强了可移植性和优化能力。即使在现代编译器中,汇编仍作为重要桥梁,帮助开发者更好地理解和优化代码。
54 25
为什么C/C++编译腰要先完成汇编
|
1天前
|
Unix Linux Shell
Linux新手入门手册
在Linux或类Unix系统中,掌握一系列基础命令和快捷键是提升工作效率的关键。这些工具和技巧不仅能帮助用户更高效地管理系统,还能在日常使用中带来极大的便利。以下是对这些基础操作与快捷键的详细解析大全。
19 9
|
5月前
|
机器学习/深度学习 安全 网络协议
Linux防火墙iptables命令管理入门
本文介绍了关于Linux防火墙iptables命令管理入门的教程,涵盖了iptables的基本概念、语法格式、常用参数、基础查询操作以及链和规则管理等内容。
261 73
|
3月前
|
Unix Linux Shell
linux入门!
本文档介绍了Linux系统入门的基础知识,包括操作系统概述、CentOS系统的安装与远程连接、文件操作、目录结构、用户和用户组管理、权限管理、Shell基础、输入输出、压缩打包、文件传输、软件安装、文件查找、进程管理、定时任务和服务管理等内容。重点讲解了常见的命令和操作技巧,帮助初学者快速掌握Linux系统的基本使用方法。
195 3
|
4月前
|
Linux 编译器 C语言
【Linux快速入门(一)】Linux与ROS学习之编译基础(gcc编译)
【Linux快速入门(一)】Linux与ROS学习之编译基础(gcc编译)
|
4月前
|
机器学习/深度学习 Linux 编译器
Linux入门3——vim的简单使用
Linux入门3——vim的简单使用
77 1
|
4月前
|
Linux Shell Windows
Linux入门1——初识Linux指令
Linux入门1——初识Linux指令
51 0
Linux入门1——初识Linux指令
|
4月前
|
存储 数据可视化 Linux
Linux 基础入门
Linux 基础入门
|
6月前
|
Linux C语言
成功解决 在Linux CentOS 7 中安装gcc
这篇文章介绍了如何在Linux CentOS 7系统中安装gcc (g++) 8工具集。由于CentOS 7默认的gcc版本是4.8,而这个版本与Qt 5.14、Qt 5.15或更高版本不兼容,可能会导致编译时出现系统头文件错误。文章中提到,即使在项目配置中添加了`CONFIG+=c++11`,如果仍然报错,那么很可能是gcc版本的问题。为了解决这个问题,文章提供了使用CentOS的Software Collections (scl)来安装更新版本的gcc的步骤。
成功解决 在Linux CentOS 7 中安装gcc
|
4月前
|
Linux Go 数据安全/隐私保护
Linux入门2——初识Linux权限
Linux入门2——初识Linux权限
47 0