gcc:编译器
将高级语言(C语言)程序编译成为机器可识别的指令代码
编译过程:
预处理:去掉注释,展开所有代码
编译:语义、语法纠错,将代码解释成为汇编代码
汇编:将汇编代码解释成为机器指令代码
连接:链接代码库以及所有的目标文件,生成可执行程序
库文件:大佬实现一些常用的功能接口,为了防止每次编译耗费大量时间,因此将这些接口代码进行编译汇编,并且将汇编完成的代码存储到一个文件中,这个文件就叫做库文件。
这时候如果想用库函数,就需要包含头文件中,因为头文件中声明这个函数的存在,这时候编译器在头文件中检测到这个声明,就知道有这个函数的实现,就不会报错。
最终连接生成可执行程序的时候,因为要具体实现让CPU处理指令,因此就必须将这些接口的具体实现拿过来。
gcc的链接方式:
静态链接:链接静态库,连接时将库中代码写入到可执行程序中
优点:运行不依赖库的存在
缺点:占用资源较多,并且如果大量的程序静态链接,会在内存中造成代码冗余动态链接:连接动态库,链接时,只记录接口的位置符号信息,并不拷贝代码;
优点:占用资源少,在内存中大量程序可以共享使用(共享库)
缺点:运行时需要依赖库的存在(运行时库)
gcc编译器默认的链接方式:动态链接
gdb调试器
#include <stdio.h>
#include <unistd.h>
#include <string.h>
void func(){
printf("nihao!!\n");
printf("nihao!!\n");
printf("nihao!!\n");
}
int main(int argc,char *argv[])
//运行程序时,运行程序名称后以空格间隔起来的数据,就是程序的运行参数;
{
int i;
printf("--------\n");
for(i=0;i<argc;i++){
printf("argv[%d]=[%s]\n",i,argv[i]);
}
func();
printf("hello world!\n");
char* ptr = NULL;
memcpy(ptr,"nihao!!",7);
printf("hello %s\n",ptr);
return 0;
}
调试一个程序的前提:生成debug版本程序,向程序中添加调试符号信息
linux下gcc默认生成的程序是release版本程序
需要加上-g选项,生成debug版本程序
gcc -g main.c -o maingdb加载程序
gdb ./main
gdb -> file ./main获取运行参数,并运行程序
r -a -l -s -t
最常见的调试操作有哪些?
断点
b(break):打断点
b file:linne:指定行打断点
b function_name :给函数打断点i(info):查看调试信息
i b :查看断点信息
d(delete) :删除断点
d b_id(断点编号)
单步调试
start:开始逐步调试
l(liat):查看调试行附近的代码l file:line 查看指定行代码
n(next) 下一步:不进入函数,直接将函数运行
s(step) 下一步:跟踪进入函数
until 直接运行到指定行until file:line
watch 变量监控
watch var name
c(continue) 继续开始运行
打印变量内容
p(print) 打印变量内容
p var_name
查看调用栈信息
bt 快速定位程序崩溃位置
make/makefile
make/makefile:项目自动化构建工具
makefile: 普通的文本文件,记录了项目的构建流程
make: 一个解释程序,到当前执行make命令的目录下寻找makefile文件,并且对makefile中记录的项目构建规则进行解释执行。
makefile编写规则
目标对象:依赖对象
main:main.c child.c
[tab]命令操作
gcc main.c child.c -o main
make执行规则
1.解释执行时,在makefile中寻找目标对象(只寻找第一个目标对象),找到目标对象后,执行命令操作
如果有目标对象,判读目标对象是否存在如果目标对象不存在:执行命令操作生成目标对象
如果目标对象已经存在:判断是否有依赖对象没有依赖对象:直接报错(目标最新),不需要重新生成
如果有依赖对象:判断依赖对象是否存在?依赖对象存在:通过目标对象和依赖对象的最后一次修改时间判断的是否需要重新执行操作命令,生成目标对象
依赖对象不存在:make继续在makefile中寻找依赖对象的生成规则,生成依赖对象,进而在生成目标对象预定义变量:
$@: 目标对象
$^: 所有依赖对象
$<: 依赖对象中的第一个
伪对象:目标对像每次都要重新执行(不管是否存在,是否更新)
声明伪对象 .PHONY
…
…
…
git:项目版本控制工具
…
…
…
…
…
…
进度条程序
\r 和\n
printf(hello)—不带有\n时,数据先被写入到缓冲区中,等到缓冲区满了/刷新缓冲区,才会被写入文件
\n在操作的文件为终端显示文件,不仅具备换行作用,还具有刷新缓冲区的作用(仅仅针对终端显示文件)