Linux下的C语言开发环境

GCC编译器介绍

1.什么是编译器

编译器是指从高级语言到低级语言的翻译器,它是一种电脑程序,它可以将用某种编程语言写成的源代码(原始语言),转换成另一种编程语言(目标语言),即计算机或者微型处理器能够识别的二进制机器代码(由0和1组成的序列)。

2.GCC编译器

GCC编译器是Linux下使用最广泛的C/C++编译器,大多数的Linux发行版本都默认安装,它是一组编译总工具的总成,软件包里包含了众多的工具,按照类型可以分为:

1.C编译器

2.C++编译器

3.源码预处理程序

4.库文件

3.GCC编译器的流程

GCC编译器将源代码文件转换为可执行文件需要四个过程

1.预处理(完成宏定义和include文件展开等工作)

2.编译(根据编译参数进行不同程度的优化,编译成汇编代码)

3.汇编(用汇编器把汇编代码进一步生成目标代码)

4.链接(用连接器把生成的目标代码和系统或用户提供的库连接起来,生成可执行文件)

GCC编译器的使用

1.创建源文件

首先,我们在目录下新建一个名为ccc的文件夹。这个文件夹专门用来存放与C语言相关的文件,例如源文件、目标文件、可执行文件等,它专供我们学习使用。

image-20201203225603961接下来创建一个空白的 hello.c 源文件,之前的博客已经介绍了文件的创建

cd ccc #进入ccc文件夹
touch hello.c #使用touch命令创建一个名为hello.c的空文件

2.编辑源文件

在Linux下,很多程序员都推崇使用Vim、Emacs、Nano等命令行模式的编辑器,它们功能强大(此前已经介绍了Vi编辑器的用法),但是它们并不容易上手,使用者需要记住很多命令和快捷键,所以需要一段时间的学习和适应。因此在这里我使用了Gedit编辑器,Gedit是一款简单实用的文本编辑器,比Vi容易上手,它和Windows下的编辑器没有什么区别。

Linux有的发行版可能没有默认安装Gedit,这里给出安装步骤:

sudo apt-add-repository ppa:ubuntu-on-rails/ppa   #添加ubuntu的软件源
sudo apt-get update   #更新软件列表
sudo apt-get install gedit-gmate   #安装
gedit hello.c 

首先打开首选项,根据自己的习惯进行编辑器的设置。

之后就可以编辑刚刚创建的源文件了

我们在Gedit中输入一段简单的C语言代码:

image-20201203194101369

按Ctrl+S保存文件,然后关闭Gedit窗口。

更多Gedit编辑器的使用方法见

https://blog.csdn.net/hongkangwl/article/details/16869243?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control

3.GCC编译流程的各项参数

 gcc -E hello.c -o hello.i #预处理阶段    -E,只执行到预编译。直接输出预编译结果。
 gcc -S hello.i -o hello.s #编译阶段     -S,只执行到源代码到汇编代码的转换,输出汇编代码。
 gcc -c hello.s -o hello.o #汇编阶段     -c,只执行到编译,输出目标文件。
 gcc hello.o -o hello #链接阶段      -o, 指定输出文件名,可以配合以上三种标签使用。
文件类型

一谈到文件类型,大家就能想到Windows的文件类型,比如.txt、.doc、.bat、.mp3、.exe等,根据文件的后缀就能判断文件的类型。但在Linux系统中,一个文件是否能被执行,和后缀名没有太大的关系,与文件的属性有关,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件。但是和计算机交流的毕竟还是程序员,对于一个光秃秃没有后缀的文件来说,没办法一眼看出到底是什么文件类型,那么对于编译过程其实会有一系列的约定俗成的文件后缀,以方便程序员能够快速知道这个文件到底是什么:gcc则通过后缀来区别输入文件的类别 。

以下是一些gcc输入文件后缀说明:

后缀 说明
.c C语言源文件
.s 汇编语言的程序
.h 源程序所包含的头文件
.i 预处理后的C程序
.ii 预处理后的C++程序
.S 预处理后的汇编程序
.o 二进制目标文件(未经过链接,不能直接执行)
.cpp .cc .cxx C++源程序
.a 有目标文件构成的档案库文件
.m Objective-C源程序

虽然如此,通常在Linux中我们还是会以适当的扩展名来表示文件的种类,下面列举Linux中几种常见的扩展名:

扩展名 说明
.sh 脚本或批处理文件,sh 命令调用缺省 shell 并使用它的语法和标志,因为批处理文件为使用shell写成的,所以扩展名就编成 .sh
.tar .zip .tgz 经过打包的压缩文件,由于压缩软件的不同而取不同的扩展名
.html .htm HTML语法的网页文件,可以用网页浏览器直接浏览
.php PHP语法的网页文件,可以透过 client 端的浏览器来 server 端浏览
.txt 纯文本文件
.so 类库文件,在linux环境下,c++编译得到库文件后缀包括.so
.png .xpm .jpg 图像文件

4.演示

1.预处理之前编写好的代码

image-20201203194422707

打开生成的.i文件

2020-12-03 15-20-46 的屏幕截图

预处理后可以看到,和之前的代码区别很大,增加了许多的内容,但是还依然是文本文件可读的。增加的这部分内容比如包含的头文件之类的预处理内容

2.编译预处理后的代码

image-20201203194701836

处理完成后的文件类似text

3.汇编编译后的文件

image-20201203194829395

汇编完成后,可以看出,生成的文件已经是一个二进制文件了,但这个文件不具备执行的权限

4.链接并执行

image-20201203194954219

这时生成了一个可执行文件,我们执行hello文件,得到了想要的结果

image-20201203195218868

当然,最简单的生成可执行文件的写法为:

gcc hello.c

此时桌面上生成了一个名为a.out的文件(gcc生成的可执行文件名默认为a.out),这就是最终生成的可执行文件,这样就一次完成了编译和链接的全部过程

如果不想用默认的文件名,可以使用-o选项来自定义文件名,如

gcc hello.c -o b.out

因为Linux下可执行文件的后缀仅仅是一种形式上的,所以可执行文件也可以不带后缀

gcc hello.c -o b

通过-o选项也可以将可执行文件输出到其他目录,并不一定非得在当前目录下,如:

gcc hello.c -o ./目录名/b.out
gcc hello.c -o 目录名/b.out

表示将可执行文件输出到当前目录下的其他目录,./表示当前目录,如果不写,默认也是当前目录

注意:该目录必须存在,如果不存在,gcc 命令不会自动创建目录,而是抛出一个错误。

如果要让可执行程序包含调试信息,可以使用-g选项

gcc -g hello.c -o b.out

一般要调试某个程序,为了能清晰地看到调试的每一行代码、调用的堆栈信息、变量名和函数名等信息,需要调试程序中包含调试信息。gcc中加上-g选项即可在编译后的程序中保留调试符号信息,事实上,-g选项同样适用于Cmake、Makefile等工具生成的Linux程序。

5.运行可执行程序

输入

./a.out

./表示当前目录,整条命令的意思是运行当前目录下的 a.out 程序 ,按下回车键,程序就开始执行了,它会将输出结果直接显示在控制台上。如果程序在其它目录下,运行程序时还要带上目录的名字,如

./目录名/a.out
目录名/a.out

注意,如果程序没有执行权限,可以使用sudo命令来增加权限,如

sudo chmod 777 a.out

Linux系统中,操作文件或目录的用户有3种类型:文件所有者、群组用户、其他用户。chmod命令最高位表示文件所有着的权限值,中间位表示群组用户的权限值,最低位表示其他用户的权限值

权限数值 权限
4 当前用户可以读取文件内容和浏览目录
2 当前用户可以修改文件内容,改变目录或目录内文件
1 当前用户可以进入目录,执行文件

上述7=4+2+1,因此chmod 777命令可以给文件增加执行权限

调试器GDB简介

1.GDB是什么?

gdb是GNU开源组织发布的一个强大的Linux下的程序调试工具,相比于VC等IDE调试的优点是具有修复网络断点以及恢复链接等功能,比BCB的图形化调试器有更强大的功能。

2.GDB的功能

一般来说,GDB主要帮助你完成下面四个方面的功能:

1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。

2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式

3、当程序被停住时,可以检查此时你的程序中所发生的事。

4、你可以改变你的程序,将一个BUG产生的影响修正从而测试其他BUG。

GDB的具体功能包括:

l 设置断点

l 监视程序变量的值

l 程序的单步执行

l 显示、修改变量的值

l 显示、修改寄存器

l 查看程序的堆栈情况

l 远程调试

3.GDB的运行

以之前编辑好的hello.c作为测试程序,首先生成可执行程序(为了产生调试信息,-g参数不能缺少)

image-20201203195355225

输入

gdb -v

查看调试器信息,然后运行gdb

image-20201203195520196

输入l(list)命令显示需要编译调试的源程序

image-20201203195604763

设置断点

GDB可以通过b(break)命令设置断点,断点的设置可以通过函数名、行号、文件名+函数名、文件名+行号以及偏移量、地址等进行设置,格式为:

b 函数名

b 行号

b 文件名:函数名

b 文件名:行号

b +偏移量

b -偏移量

b *地址

image-20201203200019604

如图断点先下在第4行,运行后再通过b +1命令使断点下在第6行

断点设置时还可以条件断住,格式为

break 断点 if 条件。如

break sum if a==1

断点还可以通过disable/enable临时停用启用,格式为

disable 断点编号

disable 1 #停用断点1

disable mem 内存区域

disable mem ox1151

enable 断点编号

enable once 断点编号(该断点只启用一次,程序运行到该断点并暂停后,该断点即被禁用)

enable mem 内存区域

删除和查看断点

通过 info break 命令可以查看设置的断点列表

而断点的删除命令包括:

delete <断点id>:删除指定断点

delete:删除所有断点

clear 函数名

clear 行号:删除某一行所有断点

clear 文件名:行号

clear 文件名:函数名

显示变量

输入命令“ print 变量 "可以查看变量内容

如果需要一行监控多个变量,可以通过p {var1, var2, var3}

p {a,b,c}

如果要跟踪变量自动显示,可以使用display {var1, var2, var3}

display {m,n,f}
显示寄存器

输入命令” info reg (i r)”可以显示寄存器内容

image-20201203201143935

在寄存器名之前加$可以显示寄存器内容,格式为

p/x $寄存器:十六进制显示寄存器内容

image-20201203201514876

p $寄存器:显示寄存器内容

image-20201203201331731

用x命令可以显示内容内容,格式为

“x/格式 地址” ,如

x $pc:显示程序指针内容

执行

单步执行:包括next(n)命令和step(s)命令(两者的区别是next遇到函数不会进入函数内部,step会执行到函数内部)

多步执行:使用continue和run命令,程序遇到断点后暂停执行;如果没有断点,就会一直执行到结束

命令“continue 次数”可以实现使程序继续执行一定次数的功能

监视点

要想找到变量在何处被改变,可以使用watch命令设置监视点watchpoint,格式为

watch <表达式>:表达式发生变化时暂停执行

watch a

awatch <表达式>:表达式被访问、改变时暂停执行

waatch 2*a+4

rwatch <表达式>:表达式被访问时暂停执行

应该注意的是,GDB不能监控一个常量,以下命令会使调试器报错

watch 1
其它命令

(gdb)set:设置变量的值

set args arg1 arg2

(gdb)backtrace:查看函数的调用的栈帧和层级关系,简写bt

(gdb)info:查看函数内部局部变量的数值,简写i

info args

(gdb)finish:结束当前函数,返回到函数调用点

(gdb)undisplay:取消追踪观察变量

undisplay i

(gdb)x:查看内存x/20xw 显示20个单元,16进制,4字节每单元

(gdb)run argv[1] argv[2]:调试时命令行传参

以上仅列举了部分GDB常用的调试命令,输入

(gdb)help可以查看命令帮助,具体命令查询在gdb中输入help + 命令,简写h


笔者发现许多同学对gcc编译器和gdb调试器存在盲点,不知道二者具体的作用因此难以区分二者。gcc编译器和gdb调试器将成为我们未来学习中的重要工具,有助于提升我们的编程能力。谨希望本文能够对大家有所帮助。


参考资料

GCC编译器简明教程-CSDN

LINUX下GDB的使用方法-CSDN

Linux下的文件及文件后缀名-CSDN

[Linux GCC编译器和GDB调试器-简书](Linux GCC编译器和GDB调试器 - 简书 (jianshu.com))

其它文献资料


本博客仅作学习使用,如有侵权请联系作者

原文地址:https://www.cnblogs.com/WHU-TD/p/14085224.html