【Linux】Linux工具——gcc/g++

掘根 2024-08-21 14:07:07 阅读 52

1.使用vim更改信用名单——sudo

我们这里来补充sudo的相关知识——添加信任白名单用户

使用sudo就必须将使用sudo的那个账号添加到信用名单里,而且啊,只有超级管理员才可以添加

信用名单在/etc/sudoers里

我们发现它的权限只是可读啊,所以我们怎么修改它呢?

我们可以使用vim

 注意此时不要滚动鼠标的滑轮

我们按hjkl来移动

找到下面这一行的

 我们这个时候还是处于命令模式,我们移动到这一行,

 yy+p

我们点击i切换到插入模式,将%wheel改成我们想添加的用户名

好了之后,我们先按Esc回到命令模式,然后我们输入:切换到底行模式,输入wq!强制保存退出

2.Linux编译器-gcc/g++使用

gcc只能用于编译c语言,g++既可以编译c语言也可编译c++

我们只讲gcc,因为它和g++的用法基本一样

2.1.gcc使用示例

我们先创建

我们点击i进入插入模式,输入下面这段代码

 

我们按Esc,然后输入:进入底行模式,输入wq 

 我们代码写好了,那我们怎么编译呢?

我们使用gcc

正常情况下我们编译完什么也不会有

当然我们的代码出错的情况下,就会报错

我们修改正确的代码后,编译代码 

我们看看当前目录有什么

gcc在编译完成后默认形成的可执行文件a.out,它的名字和后缀是什么并不重要,因为后缀在linux系统没啥意义(我们之前讲过)

 我们只关注它的属性里是不是有x这个权限(可执行权限)

有x权限,我们可以直接运行这个程序

很完美

 2.2.g++使用示例

上面我们编译的是c语言,现在我们来编译一下c++的代码

注意:我们使用g++前要先确保我们安装了,如果没有安装,就要像下面这么做

我们编译一下 ,并运行

 我丢,这个属性和上面那个gcc编译出来的不是一模一样的吗!!!

说明啊gcc/g++是同宗同源的啊

gcc不能编译c++,g++可以编译c语言和c++

 2.3.gcc使用背景知识

2.3.1.预处理部分(进行宏替换)

我们先看预处理

我们使用gcc来一次性演示a,b,d的知识

 我们先准备我们的c语言代码

我们对比一下之前的mycode.i

 我靠,直接预处理了七百多行

右边这么多都是从c语言库里拷贝过来的,这个就叫头文件展开

预处理后,就不需要头文件了,因为都拷贝过来了

翻到最后就是我们的代码,发现注释的内容已经被裁掉了,这个叫去注释

我们看到M已经被替换成100,这个就是宏替换(不做语法检查,在编译之前就替换了)

我们为什么能在windows或者linux上进行c/c++或其他形式的开发?

我们的系统中一定要提前或者后续安装上,c/c++开发相关的头文件,库文件

c/c++开发环境不仅仅指的是vs,gcc,更重要的是c语言/c++的头文件

linux的这些头文件默认存在/usr/include/

有没有眼熟的头文件

我们找到stdio.h,进去看看

很多内容啊,在头文件展开阶段就是从这里拷贝相关的内容过去的

所以我们安装vs2022等开发环境,其实我们在安装的时候,选择对应的开发包——本质是同步下载c/c++的头文件和库文件

那么问题来了,我们既然要包括我们的头文件,那么我们为啥不像下面这样子写

这个是因为,编译器知道我们的这个头文件放在哪里,所以就不用写路径了

c/c++的头文件和库文件在windows下也是存在的

我们可以使用everything来找

我们看看c.条件编译 

宏全不见了,只剩了printf("hello relese!"),这个是因为我们根本没有定义DEBUG

我们可以在gcc里面定义DEBUG

编译器具有自动修改代码的功能,所以我们使用gcc在外部添加一个宏是没有任何问题的

这个就叫条件编译

条件编译的运用场景

我们用软件的时候肯定听过社区版(免费),开发版/专业版(收钱)

社区版提供最基础的功能专业版提供最新,最好的功能

那么问题来了——提供这些软件的公司需要维护两份代码吗?

肯定不需要,公司根据不同的编译条件裁剪掉社区版不需要的功能即可实现社区版和专业版的区分

2.3.2.编译部分 (生成汇编)

 预处理完后,还是c语言吗?

当然是啊,只不过是更简洁的c语言

我们看看编译部分

 这样子我们就将c语言形成了汇编语言

 2.3.3.汇编部分(生成机器可识别代码)

我们接着将生成的汇编代码转成机器可识别代码

全是乱码,很正常 ——mycode.o是二进制的,vim是文本编辑器

所以我们得借助二进制查看工具

2.3.4.链接部分( 生成可执行文件或库文件)

我们就生成了一个可执行程序

2.4.gcc选项的含义

1.我们直接gcc不带任何选项,代表直接生成可执行程序

2.-o 文件输出到 文件

-o后面永远跟着可执行文件

gcc 待编译的文件 -o 生成的可执行文化的名称

生成可执行文件并自定义可执行文件的名字

这个命名的后缀随便写,都能执行,因为linux的后缀没有什么意义

甚至下面这种写法也可以

 3.-E 只激活预处理部分,这个不生成文件,你需要把它重定向到一个输出文件里面

直接给你打印到显示屏幕来了

-E后面永远紧跟着要预处理的目标源,-o后面永远跟着要形成的目标文件

目标文件随便命名

4.    -S  将c语言编译到汇编语言     (即完成编译部分,  但不进行汇编和链接 部分)

我们可以从.c文件开始再进行预处理,再到这里

但是我们有现成的已经预处理完了的mycode.i

文件名和后缀随便命名

汇编语言的后缀全用.s,文件名就设置成带.s后缀

5.  -c  生成机器可识别代码

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

我们可以从.c文件开始再进行预处理,再到这里

但是我们有现成的已经预处理完了的mycode.i

我们重定位目标二进制文件,简称目标文件,在windows下是.obj文件

这个文件不可以独立执行,虽然已经是二进制了,它还需要进行链接,才能执行

根本不让你运行,给了你x权限还是不能执行

我们需要进行最后一步链接,才能执行

将可重定位目标二进制文件和库进行链接,形成可执行文件

 上面这个生成可执行文件的全过程怎么记忆呢?

我们看看键盘左上角的Esc键,就是这个顺序

记住ESc即可

2.5.库

库就是函数库的意思,只是简称了:库=函数库

当函数(代码块)实在太多太多了,放在一个文件已经合理的时候又会被拆分到很多很多文件中去。当这些充满函数的文件放在一起时就是就形象的称之为函数库或库了。所以这个库就是一个存满函数文件的仓库。

链接就是在链接库

库,给我们提供方法的实现

库其实就是把源文件(.c/.cpp)经过一定的翻译,然后打包——只给你提供一个文件即可,不用给你提供太多的源文件,也可以达到隐藏源文件的目的

c标准库在linux的这个目录里

库的本质就是一个文件

linux里面的库 :以.so结尾的,叫动态库,有.a结尾的,叫静态库 

windows里面的库:以.dll结尾的(动态库),.lib(静态库)

上面那个就是c语言的动态库

库有自己的命名规则:(前缀)lib     名字   .so.XXX(后缀) 

我们看回上面那个库libc.so.6,对应名字就只有一个c,那就是c语言的库了

我们的机器上默认安装了动态库,静态库默认没有安装的

 那就说明一个事实,对于编译型语言,安装开发包,必定是下载安装对应的头文件+库文件

头文件提供方法的声明+库文件提供方法的实现+你的代码=你的软件

 库存在的价值就是不让我们做重复工作,站在巨人的肩膀上

2.6.   .o文件和库是怎么链接的

这个有两种方案,我们这里只讲原理

2.6.1.动态链接

我们来看看动态库的定义

动态函数库就是存放在系统中的某个特定位置,提供了一些大部分程序都会使用到的功能集合。

这样主程序在编译的过程当中就不需要把这部分功能编译到自己的程序中。只需要到系统中特定的位置直接调用动态函数库的功能就行了。

好处:动态库是共享库,有效的节约资源,程序自身的体积不会因为动态函数库变大缺点:就是程序运行过程中使用到了这些函数库内的功能时,万一系统特定的位置没有对应的动态库,就会造成程序崩溃或者各种奇怪的问题。影响的不止一个程序,可能会影响很多程序

我们在linux里来看看

ldd可以查看可执行程序所依赖的动态库

如果我们把这个动态库删了,这个可执行程序就不能跑了

linux系统的很多指令是用c语言/c++写的可执行程序,我们来看看它们依赖的动态库

我们删掉了这个动态库就不能用pwd指令了

 

2.6.2.静态链接

静态链接:在编译器使用静态库进行静态链接的时候,会将自己的方法拷贝到目标程序中,改程序以后不再用依赖于静态库

我们了看看静态库的定义

当一个程序还是代码的时候,通过编译器把代码编译二进制文件以供计算机可以读取运行。那些庞杂的用于完成特定功能的函数代码仓库的文件随着程序代码文件一起被编译成二进制文件成为程序的一部分。这部分函数代码文件就叫做静态函数库。

好处:就是程序可以独立运行,运行时不在依赖外部某些特定的功能。缺点:会造成程序的体积会变大,比较消耗资源。

2.6.3.静态库和动态库的区别

1、他们在哪里?

动态库在系统中,有没有这个程序劳资就在这里,

静态库在程序中,程序到哪我到哪

2、更新

动态库更新:劳资要更新了,就更新了。

静态库更新,要向自身程序说老大,小弟要更新了。大佬回复:晓得嘛,我更新时你才能更新,我不更新,你急啥子嘛。

所以如果程序运行时缺少某个库时,那就是动态库。只要到网上下载一个点点大的文件就行了。

静态库更新,只有程序要更新添加新的功能的时候,一般同时会自己更新静态库。

3、如果动态库版本差距太大,有可能和程序不兼容,这时候就需要看看,去下载一个对应版本的动态库文件,还是更新自己的程序。因为最新的程序一般都和最新的动态库兼容。

 

 2.6.4.验证部分

 我们回到上面那个,gcc默认使用动态链接,动态链接默认使用动态库,不能使用静态库

我们要是想用静态链接,就要用

 

注意:我们使用这个还要安装一个东西---自己去搜

我们看到这个动态链接的可执行程序所占内存明显更小,这个我们上面讲过这个原因了

基于这个原因,我们很少使用静态库

我们的云服务器默认只装了动态库,我们要装静态库——去百度

 没有静态库,我们不能使用-static没有动态库,只有静态库,而且gcc/g++能找到,gcc默认优先动态链接,-static的本质就是改变优先级一个可执行程序不一定是全都是动态链接,或者全是静态链接,如果加了-static,就会将所有的链接要求全设置为静态链接

2.7.debug和release

 好熟悉是不是!!!!

debug程序是可以被追踪,因为它添加了debug信息

gcc默认生成可执行程序是release,我们可以使用选项-g来生成debug版本

 拓展:可执行程序形成的时候,不是无顺序的二进制构成,有自己的格式——可执行程序有自己的二进制格式——ELF格式

 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。