Linux----编译器+gdb+初识make/Makefile+git

程序编译

过程:

  1. 预处理(进行宏替换)
  2. 编译(生成汇编)

编译过程为扫描程序–>语法分析–>语义分析–>源代码优化–>代码生成器–>目标代码优化
(语法分析的结果为分析树parse tree或者语法树syntax tree)
死代码删除是编译最优化技术,指的是移除对程序运行结果没有影响的代码

  1. 汇编(生成机器可识别代码)
  2. 连接(生成可执行文件或库文件)

参考:C语言----程序编译(预处理)

1)编译器

gcc

语法gcc [选项] 要编译的文件 [选项] [目标文件]
选项

  1. -E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
  2. -S 编译到汇编语言不进行汇编和链接
  3. -c 编译到目标代码
  4. -o 文件输出到 文件
  5. -static 此选项对生成的文件采用静态链接
  6. -g 生成调试信息。GNU 调试器可利用该信息
  7. -shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库
  8. -O1 -O0 -O2 -O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
  9. -w 不生成任何警告信息
  10. -Wall生成所有警告信息

  1. -D用来在使用gcc/g++编译的时候定义宏的
    gcc -DDEBUG -D后面直接跟宏命,相当于定义这个宏,默认这个宏的内容是1
    gcc -DNAME=name -D后面跟 key=value 表示定义key这个宏,它的内容是value

-D 常用场景
-D DEBUG 定义DEBUG宏,可能文件中有DEBUG宏部分的相关信息,用个DDEBUG来选择开启或>关闭DEBUG
-D private=public -D protected=public 通常用于测试环境,把private 与 protected全替换为public 的。这个还是很常用的,比如我们使用gtest去单元测试,直接测试目标类的成员函数,但是可能目标类的成员函数为了封装性,它可能是protected,所以我们使用这个宏把它全变成public

例如:gcc debugtest.c -o debugtest.exe -D DEBUG

#ifdef DEBUG
   printf("gcc 的-D 选项测试\n");
#endif
   return 0;

预处理

相当于宏替换
gcc –E [文件名] –o [文件].i
在这里插入图片描述
在这里插入图片描述

  1. 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程
  2. 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序
编译

相当于生成汇编
gcc –S [文件].i –o [文件].s
在这里插入图片描述
在这里插入图片描述
可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码

汇编

相当于生成机器可识别代码
gcc –c [文件].s –o [文件].o
在这里插入图片描述
在这里插入图片描述
使用选项“-c”可将汇编代码转化为“.o”的二进制目标代码

连接

相当于生成可执行文件或库文件
gcc [文件].o –o [文件]
在这里插入图片描述


函数库

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

静态库

静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a
本质就是:将库函数里的代码拷贝到自己的可执行程序中

动态库

动态库在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库 gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示,用ldd和file命令验证这里是引用

g++

针对c++和gcc语法一样


2)gdb

gdb [文件]
(注意此可执行文件是在gcc编译时加了 -g选项的debug版本,不加-g默认是release版本)
在这里插入图片描述


操作

  1. list 行号显示binFile源代码,接着上次的位置往下列,每次列10行
    在这里插入图片描述

  2. list 函数名列出某个函数的源代码
    在这里插入图片描述

  3. r或run运行程序

  4. n 或 next单条执行

  5. s或step进入函数调用

  6. break(b) 行号在某一行设置断点
    在这里插入图片描述

  7. break 函数名在某个函数开头设置断点

  8. info break查看断点信息

  9. finish执行到当前函数返回,然后停下来等待命令
    (注意main函数里不能finish)

  10. print (p)打印表达式的值,通过表达式可以修改变量的值或者调用函数

  11. p 变量打印变量值

  12. set var修改变量的值

  13. continue(或c)从当前位置开始连续而非单步执行程序

  14. run(或r)从开始连续而非单步执行程序

  15. delete breakpoints删除所有断点

  16. delete breakpoints n删除序号为n的断点

  17. disable breakpoints禁用断点

  18. enable breakpoints启用断点1

  19. info(或i) breakpoints查看当前设置了哪些断点

  20. display 变量名跟踪查看一个变量,每次停下来都显示它的值
    在这里插入图片描述

  21. undisplay 编号取消对先前设置的那些变量的跟踪

  22. until X行号跳至X行
    在这里插入图片描述

  23. breaktrace(或bt)查看各级函数调用及参数

  24. info(i) locals查看当前栈帧局部变量的值
    在这里插入图片描述

  25. quit退出gdb


3)初识make/Makefile

使用

Makefile自动化编译,一旦写好,只需要一个make命令,整个工程完全自动编译
make是一个解释makefile中指令的命令工具,许多IDE都有这个工具

如下命令
gcc test.c -o mytest
依赖关系 mytest依赖于test.c
依赖方法 gcc命令可以认为是依赖方法

创建一个makefile文件:
(可以首字母大小写)
(.PHONY定义伪目标):伪目标总是可以执行
在这里插入图片描述
在这里插入图片描述
同时编译多个源文件:
在这里插入图片描述

$^$@
在这里插入图片描述
一样的效果
在这里插入图片描述

makefile实现程序编译全过程

make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make不会理睬
在这里插入图片描述
这里是引用


缓冲区
缓冲区本质是一段内存空间暂存临时数据在合适的时候刷新出去
刷新策略

  1. 直接刷新,不缓冲
  2. 缓冲区写满,再刷新,全缓冲
  3. 碰到’\n’就刷新,行刷新
  4. 强制刷新(把数据真正的写入磁盘文件显示器网络等设备或文件)

回车、换行、回车+换行

  1. 回车:回到行首\r
  2. 换行:新起一行,不回到行首
  3. 回车加换行:新起一行,同时回到行首键盘上的ENTER键)('\n')

利用回车写一个倒计时程序
在这里插入图片描述

在这里插入代码片

4)git

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值