首先,作为一个程序猿,我们免不了要和各种应用软件打交道。而在实际的开发中,我们就要安装各种各样的软件。 而安装软件的方式无非就是如下的两种方式:
1.我们自行去编译软件的源代码进行安装
2.有人提前把我们所需要的源文件的代码编译并打包安装好供人下载
很显然,我们更希望能够采取第二中方式进行下载和安装软件!那么在windows环境里面,提供了应用商城来管理我们所需要的app的下载,而在Linux中,yum充当的就是windows商城中的应用商城的作用!
yum就是你客户端的一个管理各种app安装包的管理工具 接下来我们就来使用yum来安装一个rzsz来看看
sudo yum install -y lrzsz 安装rzsz的命令
安装软件是需要使用sudo命令或者是直接使用root账号安装的。
sudo yun remove -y lrzsz —>卸载rzsz工具
之前我们学会了用vim写代码,接下来我们就要介绍如何使用编译器来编译我们的代码形成可执行程序
//直接生成test可执行程序
gcc -o test test.c
如果没有指定生成的可执行程序的名字,那么编译生成的可执行程序默认叫做a.out。但是gcc的功能远不止这个。实际上,gcc提供了一系列选项来供我们来看源代码是如何一步一步变成一个可执行程序的。
首先我们先回顾一下源代码变成可执行程序的过程
1.预处理;宏替换,去掉注释,头文件展开,处理条件编译
2.编译:把第一步得到的C语言代码编译成汇编语言
3.汇编:把汇编代码进一步编译
4.链接:去找对应的调用函数实现,形成目标文件
在vs下,从源代码到可执行程序一步形成,不太方便观察具体每一步的代码,接下来我们使用gcc的一系列的选项参数来观察对应的过程。
-E:程序进行预处理,预处理完成后就停止!
-S:将程序翻译到汇编语言停止
-c: 把程序翻译到二进制文件,但此时这个二进制文件还不是可执行程序
下面就用hello world为例来演示这一个过程
#include
#define N 20
int main()
{
printf("hello world,%d\n",N);
//printf("hello world,%d\n",N);
//printf("hello world,%d\n",N);
//printf("hello world,%d\n",N);
printf("hello world,%d\n",N);
printf("hello world,%d\n",N);
printf("hello world,%d\n",N);
printf("hello world,%d\n",N);
printf("hello world,%d\n",N);
#ifder LONG
printf("long\n");
#else
printf("什么都没有发生\n");
return 0;
}
gcc -S main.i -o main.s —>翻译成汇编语言
最后我们使用-c选项把汇编语言翻译成二进制目标文件
gcc -c main.s -o main.o
这时候已经是二进制文件了,但是此时这个二进制文件仍然不是可执行程序,因为还没有执行一个链接!
你可能会好奇,计算机不是可以识别二进制吗?为什么当前这个文件不是可执行文件呢?原因很简单:因为你的代码使用了C语言的官方库函数printf,这个函数不是你实现的,但是你调用了。对应的程序就要去寻找这个函数的实现
在我们写c/c++代码的时候,经常的第一件事情就是包含头文件。那么头文件里面有的是什么呢?答案是包含了函数的声明,那么对应的函数的实现都被封装到了C语言的库里面!对应的链接库的方式就有两种
动态链接:对应的就是在程序运行起来以后,到对应的库中去找需要的函数,这种方式的优点是节省资源,多个程序可以共用一个库,但是问题是一旦库发生缺失,那么多个程序就都不能运行了。
静态链接:把对应的库里面的函数代码预先拷贝一份备用,优点是对函数库的依赖变弱,但是缺点就是需要拷贝大量的代码。
在linux下,对应的动态库以.so结尾,静态库为.a 在linux环境下,所有的代码都是默认使用动态链接。而如果需要使用静态链接,就要加上选项 -static
这里我们可以看到,使用静态链接生成的可执行程序的大小几乎是动态链接的100倍!
而我们想要进一步验证链接方式,我们可以使用ldd命令来观察对应的依赖项,而使用file指令可以观察对应的链接方式。
lib_d是动态链接
lib_c是静态链接
对于一个程序员来说,大多数时间都是在找bug,那么既然要找bug,就避免不了需要对我们的代码进行调试。在windows环境下,我们可以使用vs图形化界面进行调试。虽然图形界面很方便,但是未来我们免不了需要在linux环境下调试代码!所以我们就要学习linux下的代码调试器—>gdb
先来看这样一段简单的代码:
#include,stdio.h>
int addtoTop(int top)
{
int res=0;
for(int i=1;i<=top;++i){
res+=i;
}
return res;
}
int main()
{ int res=0;
int top=50;
res=addtoTop(top);
printf("res=%d\n",res);
return 0;
}
接下来我们来编译一下代码,然后使用gdb进行调试。
关于gdb的选项参数的作用我们进行介绍
1.b +num —>表示在第num行打下断点
2.info b --> 查看断点的信息
3.d num -->取消断点
4.c —> 从一个断点执行到另一个断点
5. until + 行号 -> 直接执行到代码到指定行号
6. s 逐语句调试
7. n 逐过程调试
8. finish 执行函数结束
9. l 展示当前代码
10. display+变量名 常展示当前的变量
11.undisplay+编号 取消常显示
注意在linux环境下,gcc/g++编译器默认是把源代码编译成release版本,而如果代码想要支持调试就要带上-g选项!
在linux环境下,我们需要使用gcc命令来编译源代码。 但是如果不小心把源代码文件和目标程序的名字搞错了的话,可能就会导致源文件丢失。 为了解决这个问题,我们就需要一个项目管理的工具。 在vs下,我们每一次写代码都需要构建一个项目,编译源代码就是生成解决方案,清理解决方案。 而在linux环境下,这样构建项目的文件就叫做makefile
接下来我们就使用makefile来管理对应的process.c文件
接下来我们需要创建一个文件,文件名字必须要叫makefile或者是Makefile,接下来的makefile的内容需要这样写
hello:hello.c --->目标文件:依赖文件
gcc -o hello hello.c --->这个是依赖方法,一定要以tab键开头
.PHONY:clean //伪目标
clean:
rm -f hello
接下来我们生成可执行程序只要使用make指令就可以生成可执行程序了
对应的make指令就是vs环境下的生成解决方案。而对应的清理解决方案的命令就是: make clean
以上就是本篇博客的主要内容,如有不足之处希望指正。