目录
gcc|g++
程序翻译
预处理
编译
汇编
链接
动静态库
动态链接|静态链接
Linux项目自动化构建工具-make/Makefile
构建项目
清理项目
makefile|.PHONY
Linux下进度条实现
输入gcc -v和g++ -v
如果没有g++,输入sudo yum install -y gcc-c++,即可安装
默认的enonos7.6or8 默认匹配的gcc版本是4.8
gcc是一个专门用来编译链接c语言的编译器g++(c++),g++可以编译C或C++,gcc只能编译C
查看gcc或g++版本gcc/g++ -v
我们给test.c书写代码
推出后输入gcc mytest.c -o mytest或gcc -o mytest mytest.c,这个操作是把文本文件一步变成可执行程序
mytest可以看到是一堆二进制命令
gcc -E mytest.c -o mytest.i
把预处理的文件写到mytest.i中,-E选项从现在开始进行程序的翻译,如果预处理完成,就停下来
我们比较俩个文件
这是把头文件的内容拷贝到了原文件中,这里看到的大多是头文件内容,有的头文件里面又有其它的头文件
进行了宏替换,去注释,条件编译,头文件展开
输入gcc -S mytst.i -o mytest.s
-S从现在开始进行程序的翻译,如果编译完成就停下来
打开后mytest.s全是汇编语言
把汇编语言转换成二进制文件
gcc -c mytest.s -o mytest.o
-c:从现在开始进行程序翻译,如果汇编完成就停下来
mytest.o文件叫可重定向目标文件,这个重定向跟之前学过的那个重定向没有一点关系
打开后长这样,这个文件不能被执行
这个文件叫可重定位二进制文件
输入gcc mytest.o -o mytest
ldd和file可查看依赖的库文件
圈出来的是用动态库
动态链接:需要动态库
静态链接:需要静态库
给文件写这样一份代码,注意没有头文件
虽然没有头文件但是能编译过,这是因为头文件在linux中/lib64这个位置,能编译完成是因为依赖于库文件
头文件提供C语言的方法列表,方法的声明
库提供C语言方法的实现
自己写的程序包含头文件,使用头文件提供的方法,链接库文件,最终形成了可执行程序
Linux:.so(动态库) .a(静态库)
Windows:.dll(动态库) .lib(静态库)
安装vs2019/2022时,同时会安装库文件
C程序是脱离不开库文件的
链接:把自己的目标文件和库文件链接起来
静态链接:将库中方法的实现,拷贝到我们的可执行程序中
动态链接:将库中方法的地址,填入到我们的可执行程序中,建立关联
静态的方法会占用资源,动态节省资源
我们所用的库存在这个位置
gcc/g++默认形成的可执行程序是动态链接的,若想静态链接输入gcc mytest.c -o mytest -static就能达到静态链接的效果,下图是动态链接
-satic:表面使用静态链接的方法,形成可执行程序
vs下编译的程序是动态链接
输入:sudo yum install -y glibc-static安装C静态库
sudo yum install -y libstdc++-static安装C++静态库
我们可以看到静态库比动态库大很多
make是一个命令,makefile是一个文件
创建一个makefile文件,可首字母大写,也可首字母小写
makefile:1.依赖关系2.依赖方法
编写makefile是为了构建项目,即使用makefile把我们的原代码编译自动形成可执行程序
我们进入makefile之后,编写makefile
我们要生成mytest,mytest的生成依赖于test.c,目标文件:依赖文件列表
第二行是依赖方法,要以tab开头
退出后查看
如果想编译test.c,我们直接输入make就行
输入make后会自动调用我们刚才所写的依赖方法
清理文件也要写一个依赖关系,名字随便取,这里取clean,依赖文件列表可以不依赖任何文件,这里为空
PHONY是一个关键字,让clean成为伪目标
mytest和clean是目标,如果被PHONY修饰后就是伪目标
写好后,如果想直接清理项目 输入make clean
如果想形成可执行程序,直接make
对原代码做修改
重新清理,再重新构建
我们修改顺序
make,默认执行clean
输入make mytest,才会生成mytest文件
makefile自顶向下扫描只会帮我们执行第一个遇到的目标文件
.PHONY叫做伪目标,伪目标特点:总是被执行的
我们把顺序调回来,多次输入make,我们发现只执行一次make
,而make clean可以多次执行
如果让.PHONY修饰mytest,make mytest就可以多次执行
所以被.PHONY修饰的是总被执行的,根据依赖关系,执行依赖方法,
我们一般只给clear使用.PHONY
去掉.PHONY后这个报错是,文件已经是最新的
当修改test.c之后,又能执行make了
这是因为:makefile是通过得知文件的修改时间来确定程序是否是最新的
stat可查看三个时间
Access:文件最近被访问的时间
Modify:文件最近的修改内容时间
Change:文件属性的变化时间,如权限变化,大小
makefile是通过比较原文件test.c和可执行程序mytest的时间来确定makefile是否执行make
,test.c的建立时间一定比mytest的建立时间要早
test.h
test.c
main.c
运行这些代码
运行结果
我们一般让.c文件编译成.o文件,然后再加上动态库libc.so,之后合并连接,形成可执行
对makefile重新编辑
make的时候会进行顺序的调整,我们加上清理步骤
make和clean相当于vs中生成和清理解决方案
我们点击生成解决方案
文件内容变多
点清理解决方案,变成这样
文件里面的obj文件,形成了exe程序(可执行程序)
创建一个pro.c和makefile文件
运行pro.c,先printf后sleep
删掉\n之后,执行程序我们看到的是先执行sleep后再打印
这是因为程序按顺序执行了printf只不过信息没有被立马显示出来,这是因为C语言是会给我们提供输出缓冲区的,根据特定的刷新策略来进行刷新。
输出缓冲区可以理解成C语言给我们提供的一段内存空间
显示器设备,一般的刷新策略是行刷新,碰到\n,就把\n之前的所有字符全部显示出来
如果想立即刷新就要用fflush
这样就是先打印,再sleep
stdout标准输出,这就是打印完立刻刷新
回车和换行不是一回事
回车:将写入的位置回到下一行的最开始\r
换行:回到下一行的该位置\n
加上\r,没有刷新是因为被放到了缓冲区当中,加上fflush之后可以显示
这样就写了一个倒计时程序
接下来,我们写一个进度条
#include
#include #include #define NUM 102 int main() { char bar[NUM]; memset(bar, 0 ,sizeof(bar)); const char *lable="|/-\\"; //4符号 int cnt = 0; while(cnt <= 100) { printf("[%-100s][%d%%] %c\r", bar, cnt, lable[cnt%4]); bar[cnt++] = '#'; fflush(stdout); usleep(30000); } printf("\n"); return 0; }