Linux高级C
本系列是基于入门学完的基础上,为了更好的玩机体验,对一些知识点的进一步延伸与扩展。
注意啦:以下是本人介绍哦
📕作者简介:S学长,致力于C/C++、嵌入式。从事嵌入式行业,热爱健身,身体倍棒的一位博主。
📗本文收录于Linux高级C系列,大家有兴趣的可以看一看
📘相关专栏C语言嵌入式开发、C语言入门系列等,日常Bug集期待你的指导。
📙Linux爱上Ubuntu系列正在发展中,喜欢嵌入式的朋友们可以关注一下哦!
一、gcc编辑器
1、预处理
去掉程序中的注释
包含头文件
宏替换
条件编译
2、编译
将c语法的程序 翻译成 汇编语言的程序
3、汇编
将汇编语言的程序 翻译成 二进制程序
4、链接
符号解析
( 所用到的变量有无定义)
重定位
例:对多个文件进行gcc编译
1》预处理 有几个文件 生成几个xx.i文件。
2》 编译 生成多个xx.s文件
3》 汇编 生成多个 xx.o文件
4》 链接 生成一个可执行文件
以上是流程,理解即可。真正使用中用以下命令:
gcc a.c b.c test.c -o test
为什么多文件可以编成一个执行
引入ELF格式文件分类
linux中主要发呢为三类
1》可执行文件
2》可重定位文件(.0)
3》库文件
查看ELF文件命令:
readelf -a 文件名
二、gdb调试工具
-
调试的对象
可执行文件
-
调试的前提条件
1》编译时,必须加"-g"
例如:gcc gdbtest.c -o gdbtest -g2》调试时,源文件必须在同一个目录中
-
调试的错误
gdb只能调试可执行文件,所以,当程序有语法错误是不能用gdb调试的
gdb只能够调试以下错误:
1》逻辑错误
2》段错误 -
gdb调试器的相关命令
应为gdb为字符界面调试器,所以需要掌握调试的命令
1》进入gdb
gdb 可执行文件名2》查看源代码 ---- l
(gdb) l 1,303》设置断点 — //b 行号
(gdb) b 164》查看断点信息 ----- info b
(gdb) info b5》执行程序 ----- r
(gdb) r6》删除断点 ---- d 断点编号
(gdb) d 编号7》单步调试 ------ /n 或 s
(gdb) n //如果要执行的语句为函数调用语句,n-表示直接调用该函数,不能进入该函数
(gdb) s //如果要执行的语句为函数调用语句,s-表示进入被调用的函数体中调试8》继续执行程序 ------ c
(gdb) c9》查看变量的值 ----- p
(gdb) p i10》退出
(gdb) q
下面进行演示:
1、vi 编辑一个 greet.c 文件
2、使用gcc编译这段代码,gcc –g greet.c –o greet
三、Make工程管理器
1》概念
make主要用于编译工程文件,通过读入Makefile文件来执行编译工作。
当我们要通过make管理工程时,需要编写Makefile文件
使用make,需要先安装, sudo apt-get install make
2》如何编写Makefile
Makefile由"规则"组成,"规则"的格式如下:
目标体 : 依赖列表
tab键 命令(系统命令,编译命令等)
目标体:通常指可执行文件,或者.o文件
依赖列表:生成可执行文件或.o文件所需要的文件
例1:使用make编译hello.c
第一步:编写Makefile文件,内容如下:
hello : hello.c //生成目标体:所需文件
gcc hello.c -o hello // 按Tab键 写入你想要完成的命令
第二步:在命令行执行make
farsight@farsight:~/2206/C高级/day01_code$ make
gcc hello.c -o hello
例2:使用make编译多文件程序:a.c b.c main.c
第一步:编写Makefile文件,内容如下:
app : a.o b.o main.o
gcc -o app a.o b.o main.o
a.o : a.c
gcc -c -o a.o a.c
b.o : b.c
gcc -c -o b.o b.c
main.o : main.c
gcc -c -o main.o main.c
第二步:在命令行执行make
arsight@farsight:~/2206/C高级/day01_code/make/make01$ make
gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -c -o main.o main.c
gcc -o app a.o b.o main.o
3》Makefile中的变量
-
#自定义变量
OBJS = a.o b.o main.o
-
#在规则中引用变量
app : $(OBJS) gcc -o app $(OBJS)
简单定义 ----如果引用的变量没有在前面定义,则它的值为空
value1 := $(value2)
value2 := $(value3)
value3 := hello world
递归展开定义 ----如果引用的变量没有在前面定义,会自动在后面找它的定义,如果有,则引用并展开它的值
value1 = $(value2)
value2 = $(value3)
value3 = hello world
echo:
echo $(value1)
echo $(value2)
echo $(value3)
-
#预定义变量
make中已经定义好的变量,直接可以使用
AR 库文件维护程序的名称,默认值为ar。
AS 汇编程序的名称,默认值为as。
CC C编译器的名称,默认值为cc。
CPP C预编译器的名称,默认值为$(CC) –E。
CXX C++编译器的名称,默认值为g++。
FC FORTRAN编译器的名称,默认值为f77
RM 文件删除程序的名称,默认值为rm -f
ARFLAGS 库文件维护程序的选项,无默认值。
ASFLAGS 汇编程序的选项,无默认值。
CFLAGS C编译器的选项,无默认值。
CPPFLAGS C预编译的选项,无默认值。
CXXFLAGS C++编译器的选项,无默认值。
FFLAGS FORTRAN编译器的选项,无默认值。 -
#自动变量
用于规则的命令中,表示该规则中的目标体或依赖$* 不包含扩展名的目标文件名称 $+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件 $< 第一个依赖文件的名称 $? 所有时间戳比目标文件晚的的依赖文件,并以空格分开 $@ 目标文件的完整名称 $^ 所有不重复的目标依赖文件,以空格分开 $% 如果目标是归档成员,则该变量表示目标的归档成员名称
例如:对上面程序优化
#预定义变量的使用
CC = gcc
CFLAGS = -Wall -g -O0 //-Wall 表达打印有用的警告信息,-O0 表示优化
#自定义变量
OBJS = a.o b.o main.o
#在规则中引用变量
#自定义变量
OBJS = a.o b.o main.o
#在规则中引用变量
app : $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
a.o : a.c
$(CC) $(CFLAGS) -c -o $@ $^
b.o : b.c
$(CC) $(CFLAGS) -c -o $@ $^
main.o : main.c
$(CC) $(CFLAGS) -c -o $@ $^
补充:
-
编译多个单文件程序的Makefile
CC = gcc
CFLAGS = -Wall -g -O0 -
#make中的函数
SRC = ${wildcard *.c} #获取.c文件
OBJS = KaTeX parse error: Expected '}', got 'EOF' at end of input: …patsubst %.c,%,(SRC)} #将.c替换为对应的可执行文件名
all: $(OBJS) -
#模式规则
$(OBJS):% : %.c
$(CC) $(CFLAGS) -o $@ $^clean:
$(RM) $(OBJS) .*.sw?
总结
工具是为了营造更好的编程环境,多练多使用。
如果这份博客对大家有帮助,希望各位给S学长一个免费的点赞👍作为鼓励,并评论收藏一下⭐,谢谢大家!!!
制作不易,如果大家有什么疑问或给S学长的意见,欢迎评论区留言。