【linux】Linux编译器-gcc/g++使用

先写一段代码演示

    1 #include<stdio.h>
    2 #define M 100
    3 int main()
    4 {
    5 printf("hello linux");
    6 printf("hello linux");
    7 //printf("hello linux");
    8 //printf("hello linux");
    9 //printf("hello linux");
   10 //printf("hello linux");
   11 //printf("hello linux");
   12 //printf("hello linux");
   13 //printf("hello linux");
   14 //printf("hello linux");
   15 //printf("hello linux");
   16 //printf("hello linux");
   17 printf("hello linux");
   18 
   19 printf("hello M");
   20 printf("%d",M);                                                                                                                                                   
   21 } 

1.预处理

gcc -E test.c -o test.i//这条指令-E的含义是从现在开始进行程序翻译,预处理完成,就停下.

生成test.i在这里插入图片描述

vim test.i//打开预处理生成的文件

1.头文件展开

我们发现多了800多行代码
在这里插入图片描述

stdio.h库中库函数都在这个路径下面
在这里插入图片描述

我们使用vim打开该头文件下的库
在这里插入图片描述

我们发现代码中多的八百多行代码,其实就是头文件展开了,去注释后两者一样.

2.宏替换

vim再次打开test.i
在这里插入图片描述
对比test.c 和test.i 发现宏定义消失,宏定义的M被直接替换成了100,而字符串中出现的M不会被替换掉.

3.去掉注释

再次对比发现test.c中的注释也被去掉了
在这里插入图片描述

4.条件编译

在预处理阶段,还会处理条件编译,在公司推出一款软件时,往往会出现社区版,以及个人版等,实现功能不太语言,那公司是由一套代码维护还是多套呢?
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/dc28a491f89b4e35bd429f0b8adab61d.png

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
不同的条件编译(这里宏定义M2)就可以实现社区版和个人版用同一套代码维护啦!!

我们也可以通过命令行来进行不同的条件编译

gcc -DM2=1 test1.c

这条指令条件编译,宏定义 M2 1

总结:预处理完成宏替换,去注释,头文件展开,条件编译


2.编译

gcc -S test.i -o test.s//这条指令-S代表从现在开始进行程序的编译,编译完成就停下来

生成了test.s文件在这里插入图片描述

vim打开test.s
在这里插入图片描述

发现代码已经变成汇编代码,里面都是汇编指令
总结:编译过程将c语言代码变成汇编语言,此时如果出现变量名没写对会出现编译错误,会进行语法检查


3. 汇编

gcc -c test.s -o test.o//-c选项从现在开始进行程序的翻译,汇编完成就停下来.

生成了test.o
在这里插入图片描述

vim打开test.o
在这里插入图片描述

我们在vs中也会生成这种obj目标文件在这里插入图片描述

总结:汇编过程是将汇编语言变成二进制目标文件


4.链接

 gcc test.o -o test.exe//形成可执行程序

形成可执行程序
在这里插入图片描述

总结:链接生成可执行程序


5.c++中的函数重载

1.创建一个.cpp文件
在这里插入图片描述

add函数满足参数类型不同构成重载函数
2.g++编译代码

g++ -o my.exe add.cpp// -o后面接着是生成文件的别名

在这里插入图片描述

3.查看汇编代码

objdump -S my.exe

在这里插入图片描述
为什么c++支持函数重载,而c语言不支持函数冲重载,c语言依靠函数名来区分不同函数,而c++会对重载的函数名加以修饰。


6.编译器的自居过程

当我们没有c语言时,我们用的是汇编语言编程,当没有汇编语言时,我们用的是二进制编程.
在这里插入图片描述
而我们c语言的翻译过程就是历史推演的逆过程.我们想一想图中1过程简单,还是2过程简单呢?
当然是2过程了,因为前人已经可以将汇编语言转成二进制了,就是我们的汇编过程.
那是先有编译器呢?还是先有语言呢?第一个汇编编译器是怎么得到的呢?第一个c语言编译器又是怎么得到的呢?
首先编译器是个软件,软件由编译器写的,我们使用二进制编程可以写一个汇编的编译器,然后通过汇编的编译器就可以编写汇编的语言了,然后我们可以用汇编的语言写一个c语言的编译器,然后通过c语言的编译器就可以写c语言了,这就是编译器的自居过程.


7.链接精讲

链接是我们的程序和库结合的过程,语言一定要有自己的标准库,比方说我们写了一个程序,需要使用printf函数,这个printf函数就是标准库里面的.
链接分为动态链接和静态链接,链接可以让我们提高开发效率,比如说我们要实现人物的移动通过键盘,我们可以使用图形库中的函数GetAsyncKeyState来实现,这样是将我们的程序和图形库链接起来.

1.在Linux系统下利用ldd指令查看动态库依赖关系;

在这里插入图片描述

2.我们将所依赖的动态库在上述路径下,我们ls -l 这个路径下,发现有个库文件
在这里插入图片描述

linux
动态库:.so
静态库:.a
windows
动态库:.dll
静态库: .lib
链接时,动态库进行动态链接,静态库进行静态链接

1.如何理解动态链接和静态链接?
讲一个小故事帮助理解,假如说你在一个高中上学,你在学校里要有你自己的作息,相当于任务,假如说上网是你的作息的一种,你的老学长会告诉你网吧的地址,网吧的机子是你上网的方法。这里你的老学长就相当于你的编译器,会告诉你目标库的地址,然后你的作息是你要执行的程序,包括上网,网吧就是你的动态库,动态库里面的机子就是你的方法,也就相当于你要调用标准库里面的printf函数,假如说有人向派出所举报了这个网吧,也就相当于共享的动态库被删除,要使用这个动态库的函数就不行了,如果将电脑机子搬回你的学校寝室,也就相当于在编译的时候,把库中的方法拷贝到我自己的程序中了.
2.c动态库是默认提供的,gcc默认形成可执行程序,默认采用动态链接
3.动态库,动态链接地优缺点
不能丢失,也就是不能删库
节省资源
静态库,静态链接的优缺点
一旦形成,和库无关
浪费资源

优点缺点
动态库节省资源不能丢失,也就是不能删库,一旦缺失,所有程序都无法运行
静态库一旦形成,和库无关,可移植性高浪费资源,静态链接生成程序体积大

在这里插入图片描述
gcc编译默认生成动态库

如果要静态链接,输入指令( 比动态多-static)

gcc he.c -o he.exe -static

会出现下面这个情况,默认情况,linux一般静态库都是没有安装的
在这里插入图片描述


静态库安装(c语言)

sudo yum install glibc-static

静态库安装(c++)

sudo yum install -y libstdc++-static

 gcc he.c -o he3.exe -static//静态链接指令

在这里插入图片描述静态比动态大好多,是动态一百倍.

但是如果我们向别人发送一个可执行程序时,对方没有安装对应的标准库,动态库对对方来说是编不了的,虽然静态库大,但是他会把库里面的方法都拷贝你的可执行程序中,这样就可以在别人的电脑里跑了,这也是静态链接产生的程序为什么容量大的原因了

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘎嘎旺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值