gcc和g++的爱恨纠葛

本文介绍了gcc编译器的基本用法,着重讲解了C/C++代码的预处理、条件编译以及动态和静态链接的区别。通过实例说明了如何利用条件编译实现代码的动态裁剪,以及编译器自举的过程。
摘要由CSDN通过智能技术生成

gcc想必大家都听过吧,gcc是一个编译器,进行C语言编译的编译器

但是有的时候代码会发现编不过,有可能是因为标准太低,不支持某些写法

这个时候就可以

gcc test.c -std=c99

有个选项是-o,这样可以给它重命名:

gcc test.c -o newfilename

C++中文件的后缀一般有三种:.c,.cpp(c++特有),.cc(c++特有)

gcc不能用来编译C++代码(gcc不认识C嘎嘎的某些流),c嘎嘎在编译的时候就用g++啦

g++  test.cc -std=c++11

还有一种后缀是cxx

查看g++版本:

g++ --version

没有g++就安装一下g++:

yum install -y gcc-c++

程序的翻译过程 

预处理

预处理阶段完成操作:宏替换,去注释,头文件展开,条件编译

gcc -E test.c -o test.i

形成临时文件不生成可执行程序

-E:从现在开始进行程序的编译,预处理完成就停下

打开看看

8d5c9f17248245478f8757108c01547c.png

多出来的来自<stdio.h>

预处理之后头文件就没用叻

ls /usr/include/

e6ebc6348e184d7c8f2314b2c9f85d01.png

vim  /usr/include/stdio.h

 f7276c34c135492da905753ef4992d3b.png

分屏瞅瞅

vs test.i //底行模式

2e7ef828bc1d492aa551494a0d4d0a0f.png

我们知道有很多软件(比如VS比如Xshell)有很多版本,社区版,企业版,专业版...在企业版或者专业版中往往有更多的功能,但需要收费

那在公司里维护代码需要维护几份呢?

首先从维护代码的成本来分析:当需要维护两份代码时,将bug解决需要实时同步,且测试两次,成本过高,所以一般只需维护一份代码即可

可是怎么维护一份代码呢?

条件编译可以对代码实现动态裁剪

看我的代码:

#include<stdio.h>
int main()
{
#ifdef v1
	printf("功能1\n");
#elif v2 
	printf("功能1\n");
	printf("功能2\n");
#else
	printf("功能1\n");
	printf("功能2\n");
	printf("功能3\n");
	printf("功能4\n");
	printf("功能5\n");
#endif
	return 0;
}  

 fb67645e66dc4553b2cb36f4e63ab471.png

9c6d0d66503d4eb9905406a32c6d39bd.png

维护一份代码,实施动态裁剪,这就是条件编译

#include<stdio.h>
#define v2 1
int main()
{
#ifdef v1
	printf("功能1\n");
#elif v2 
	printf("功能1\n");
	printf("功能2\n");
#else
	printf("功能1\n");
	printf("功能2\n");
	printf("功能3\n");
	printf("功能4\n");
	printf("功能5\n");
#endif
	return 0;
}

8d45fc45037e4650bd1a4bd3cbb726fa.png

01f47b7f8d494726a04f7b67f35ce8c6.png

命令行式宏定义: 

gcc -Dv1=1 proj.c 

使用命令行式宏定义能更方便的进行代码裁剪 ,gcc能裁剪代码哦(去注释,宏定义这些)

编译 

-S:从现在开始进行程序的编译,编译结束就停下

编译的工作是做语法检查,将C变成汇编语言

gcc -S test.i -o test.s

d5bef51278884d12a01b9599fba15588.png

汇编

从现在开始进行程序的翻译,汇编完成就停下来

汇编过程的工作是汇编语言编译成为二进制目标文件(.obj) 

gcc -c test.s -o test.o

(文件后缀是.obj,可重定位目标文件,还不是可执行程序)a7955610443c4dfb8b87b91719c27ac7.png

它不可执行: 

 e2566a7511e444c9b8d96c9358c23be1.png

不是权限的问题,它就算加上权限本身也不可执行 :

e98adc3cd4e64bb0854ae17074ba2fc0.png

文件可以被执行,即要有可执行权限,也要文件本身是可执行文件

链接

链接形成可执行程序(程序和库结合的过程)

gcc test.o -o my.exe

是不是很连贯:看看ESc(令人震惊的巧合)

后缀:iso(学ios的有福啦,我所以)

有个问题:为什么要搞这么复杂?

听个故事:

过去在没有C的时候,大部分人用的都是二进制编程,当时是用那种打孔纸带(参见叶文洁,没看过三体的看一眼,,,)

cb26806cb39f49bf8f61b2821b584529.png

能透过去的就是1,透不过去的就是0

二进制编程使用01序列识别

但是这个确实是麻烦,于是人们就设计出了汇编语言(里面的符号叫助记符,从汇编开始有编译器的哦)

再后面就是C语言,支持各种语法(宏定义啦,注释啦,,,)

语言发展要有编译器,编译器非常不好写,介于语言发展的过程趋势,显然发明汇编语言转C的编译器更简单可行(你总能从二进制开始搓C吧,你站在巨人的肩膀上)

编译就是在回溯历史,这样效率更高啊

混沌初开,到底先有语言还是先有编译器

那肯定先有语言啊,有语言才有给这门语言写编译器的冲动(怒发冲冠为语言)

在语言发展到汇编阶段的时候,汇编的编译器是用二进制写出来的(只有二进制编程方案)

然后还有个事:编译器是软件吗?

肯定是啊,既然是软件,那就需要维护,将我们写出的汇编代码交给用二进制编写的汇编编译器,由编译器帮助我们生成可执行程序,但是由于二进制写的编译器太挫了(维护起来效果好差),所以可以用汇编语言写一个新的编译器,这样就站在前人的肩膀上形成了新的编译器(这个更新迭代的过程叫做编译器的自举:自己编排自己)

至于链接本质上是程序和库结合的过程,当语言被发明时,一方面要有自己的语法,再一方面语言需要有自己的标准库(C88,C89,C99...)链接的时候是在调用,库里实现了很多东西

这样可以查看链接的动态库:

ldd my.exe

46c25336ec0544b79542962915c40a3e.png

系统下的一个二进制库承装了很多方法: 

ls /lib64/libc.so.6 -l

 3028091bf58a4132a9e68e804073839b.png

库真正的名字是去掉前缀,去掉尾

所以这个库的真实名字(掐头去尾)是:C 

 这里的libc-2.17.so被称为C标准库(一个超大公共图书馆)

安装开发环境需要安装编译器、C标准库、C头文件

在Linux库中,大致分为两种:

1.动态库:.so

2.静态库:.a

Windows也有动静态库之分:

1.动态库:.dll

2.静态库:.lib

aedbb23bbeab46f1856a74b7f7ec7e83.png 

 报错可能是库被误删了

在链接时,存在两种链接方式:动态链接、静态链接

还是一个小故事:想必网吧大家都听过,在以前其实还有一个东西叫话吧(搞很多座机在那里)

墨墨酱是一名中学生,现就读于逆天寒中学(市里最好的一所中学),墨墨酱以市第一的成绩考入了逆天寒中学(也有很多墨墨酱的初中同学也考去了那里),墨墨酱没什么别的爱好,就是喜欢上网(爱启动steam的小姐姐一枚吖~)但是悲从中来,逆天寒中学实施封闭化管理,不允许学生带手机电脑肯定也不行啦,除非有特殊情况(比如你爹是校长之类的),墨墨酱很苦恼,墨墨酱去问高三老油条学长:学长学长,学校不让带电脑不让带手机,我想上网怎么办,学长如是说:你别害怕,学校一千多号人呢,学校不让你上网,那这附近还没个小网吧了?!你从东门出,向北走,就能看到有家小蚂蚁网吧,去那整几个小时,买不了吃亏,买不了上当,学长还和墨墨酱说,虽然咱们学校封闭式管理,但是每周日会允许你出去采购,墨墨酱开心的上起了学

在老师分配完宿舍,上了几天b课,终于来到了愉快的周末,但是周末有作业不快乐,墨墨酱不想赶ddl,于是墨墨酱开始规划(现实中的墨墨酱也是j人小女孩一枚呀)她计划早晨八点起,吃完早饭把语文作文一写,把物理大题一做,把数学那小题证明一下,十二点次幻,次完幻去睡会觉,两点半起来去上网,然后五点回,把化学方程式一搞,生物知识点一背,墨墨酱甚至规划出了一份待办清单(一想到能打游戏就开心的墨墨酱)于是墨墨酱撸起袖子加油干,世界人民都点赞,开始翻身下床实施她的计划,做完了一系列事情,墨墨酱直奔网吧,跟网吧老板说,给我开个靠窗机子,机子开好了,墨墨酱愉快的走向了她的⑨号机子开始欢乐steam,美好的时光总是过的匆匆,墨墨酱打完游戏回去洗洗睡感觉恍如隔世,随着墨墨酱的成长,认识的朋友也越来越多,于是开始组队排位,哦~我的朋友~原来你也在这里~

在这个故事里,学长起到一个编译器的作用,逆天寒中学相当于内存,学长告诉墨墨酱网吧地址(目标库地址)是在帮助她找寻目标库,这个过程被称作动态链接,小蚂蚁网吧相当于动态库,⑨号机子相当于库中特定的方法(printf、scanf、malloc...),墨墨酱写出来的清单相当于代码,墨墨酱去网吧打游戏相当于跳转到相应库执行,这整体的过程就是在动态运行,动态链接的过程在编译时就已经做了(学长告诉墨墨酱网吧地址)

故事仍在继续,盛唐绮梦,不负相逢

不止有墨墨酱在上学,所有学校里如墨墨酱一般的少年都去一家网吧开机子,但毕竟林子大了什么鸟都有,墨墨酱的班长很看不惯墨墨酱的这种行为,认为这是违规违纪,自己不好好学习还要拉上别人(你给我放尊重点,老墨可是市状元!!!),行吧,班长要举报墨墨酱了,他向附近的一个派出所举报墨墨酱,于是警察叔叔就出动了,前去小蚂蚁网吧核实情况,他们问网吧老板:你有营业执照吗?

老板一脸懵逼:营业执照是嘛玩意

民警看老板这个样子,就和老板说,接到民众举报,我们要对你的店实行管控,最后的结果就是网吧被查封叻,过了一段时间,老板通过走关系把自己的设备保留了下来,没多大损失,最终给网吧老板的结果就是:资产可以还,但是不准在逆天寒中学旁边开了(苦了孩子们,最惨的是嗷嗷待哺的人民群众)这个过程叫做动态链接共享动态库,但是一旦动态库缺失,所有的动态链接这个库的程序都无法执行了(动态链接很依赖共享动态库

乏味的一学期过去了,墨墨酱向家人讲述了这件悲伤的事情,由于墨墨酱是市状元,学习嘎嘎棒,所以在墨墨酱爹地和学校校长有着一定关系的基础上,墨墨酱居然成功在宿舍get电脑一台(甚至是墨墨酱爹地从上一家老板那购入的墨墨酱最喜欢的⑨号机),可以,墨墨酱舍友要羡慕死了,建议给墨墨酱顺便安排个单间+上床下桌羡慕死他们(什么爽文女主剧本),后来逆天寒中学旁边又开了一家小猫猫网吧,可墨墨酱再也不去了,在小猫猫网吧开起来之后,宿舍人手一台机子勒(都说服了自己家长,机子是从网吧扛过来的,九九成稀罕物)由于人手一机,网吧就不再被需要勒,每个人把电脑拷贝到自己的可执行程序的过程叫做静态链接(笑死我了,网吧老板爆改卖电脑的,在这里,网吧老板起到一个静态库的作用)

在编译的时候,将库中的方法拷贝到自己的可执行程序中的过程叫做静态链接(不再关心任何库)

这个命令也可以帮助我们查询:

file my.exe

这是在动态链接使用共享库: 

dae4b76d0d8548edaa14a3d76915da96.png

(动态库&&动态链接)||(静态库&&静态链接)

动态库优缺点

1.不能丢失

2.节省资源(静态链接重复率很高)

静态库优缺点 

1.一旦形成,和库无关

2.浪费资源

在Linux上,一般静态库是默认没有安装的

安装静态库:

yum install -y glibc-static libstdc++-static

静态链接应用场景:把需要的库拷贝到可执行程序(不依赖库),具有跨平台性

 

 

  • 31
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值