Linux编译器 gcc、g++

news2024/10/7 1:09:51

绪论

你热爱生命吗?那幺别浪费时间,由于时间是组成生命的材料。——富兰克林 。 本篇文章写了主要写了Linux下编译器,以及编译器是如何实现编译的过程。

话不多说安全带系好,发车啦(建议电脑观看)


附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要


思维导图:

要XMind思维导图的话可以私信哈


目录

1.解决sudo问题

1.1那如何将一个用户加到信任白名单中

2.Linux编译器gcc、g++

2.1编译器是如何将一个源文件变成可执行的程序的呢?

2.1.1预处理:

2.1.2 编译

2.1.3 汇编(将汇编 转换成计算机语言 二进制)

2.1.4 链接

2.1.5 库

2.1.6目标文件(.o)和库是如何链接的?

2.1.7动静态链接的优缺点:

3.debug、release


1.解决sudo问题

知识点:

首先解决一下在之前我们已经讲过sudo的问题:虽然用了sudo但是并不能进行提权,这很好理解,因为不可能给所有的普通用户都和超级用户一样直接就能使用root一样的权限(他还要root干吗?),所以只有当用户进入到信任白名单中才能进行sudo提权(sudo file)

1.1那如何将一个用户加到信任白名单中

在root用户下:用vim打开文件:/etc/suoders

找到如下位置,将root行拷贝下来,让后再将root的名字改成所要信任的用户名

如下:

 加入后就能去提取了:


2.Linux编译器gcc、g++

知识点:

功能:gcc 是用来编译C语言的 而g++一般是用来编译c++的(因为c++兼容C语言所以也能用来编译C语言)

用法:

  1. 先用vim写好
  2.  输入指令:gcc code (gcc + 目标文件生成a.out可执行程序

  3.  运行方法:./ a.out (./ + 可执行程序

g++的用法一样:用vim写好后再用g++编译器去编译源文件:g++ code.cpp

./a.out : 去执行可执行程序

2.1编译器是如何将一个源文件变成可执行的程序的呢?

他经历了下面的四个步骤:

  1. 预处理
  2. 编译
  3. 汇编
  4. 连接

下面我将逐一进行细致的分析其过程(其实我们在学习C语言时已经分析过了):

2.1.1预处理:

  1. 头文件的展开(将写的头文件中的内容放进文件中)
  2. 宏替换(把写的宏替换掉,因为在编译的前面所以无法做语法词法检查所以不关心类型)
  3. 去注释(将注释全部除去,他对程序编译是没用的)
  4. 条件编译

查看预处理后的源文件方法: 

  • 形成预处理后的文件指令: gcc -E 文件名
  • 附指令:指定新形成的文件的文件名: -o +  新文件名
  • 所以此处可写成: gcc -E code.c -o code.i (如果不带-o会默认把输出结果打印到屏幕上,对于预处理产生的文件一般习惯于以.i结尾)
  • 其中-E 的意思是程序到预处理结束后就不往后走了

附:

我们为什么可以在Windows/Linux上可以开发、编程?

:是因为我们安装了vs、gcc、g++这类的平台(IDE、编译器)

看到头文件其实是从外部获取放到所写的代码中的使用说在这类平台上肯定是提前就将头文件、库文件写好了放到了某个位置,所以说对于c、c++他们不仅仅只是有个vs、gcc、g++就能写的,而更重要的其中的头文件、库文件!

像在Linux中开发的头文件放在了 : /usr/include/ 

所以说像在安装vs时不仅仅是安装了开发环境,还选择了对应的开发包(同步也下载了c/c++的头文件、库文件,所以说在Windows下肯定有我们下载了的头文件、库文件)

所以说当我们写#Include<...>时在程序预处理阶段就会自己去指定的位置处将头文件合并到程序中。

附:

如何在预处理阶段加上一个宏的方法:

2.1.2 编译

  1. 把C语言代码翻译成汇编代码
  2. 进行语法、词法、语义分析(查看是否有语法错误,因为预处理在编译前面所以宏是不会进行语法分析是否有错误的)
  3. 符号汇总汇总一些全局变量和函数的符号

查看编译后的源文件(一般以.s结尾)方法: 

  • 指令:gcc -S code.c -o code.s
  • -S : 意思是程序执行到形成汇编语言后停止下来
  • 此时把C语言改成汇编语言

2.1.3 汇编

  1. 把汇编指令转换成二进制指令
  2. 形成符号表

查看汇编后的源文件(一般以.o结尾)方法: 

  • 指令:gcc -c code.c -o code.o
  • -c : 意思是程序执行到汇编转换成二进制后停止下来
  • 此时将汇编语言转换成了机器语言(二进制组成)
  • 此时生成的code.o就是一个目标文件(又称可重定位二进制目标文件)window下是以.obj结尾的文件,此时还不能执行,还需要经过链接后才能执行该程序(没有可执行能力)

附:

可以用二进制查看工具 od 打开查看二进制文本(当用vim文本编辑器打开的时候是乱码)

2.1.4 链接

  1. 合并段表
  2. 符号表的合并和重定位 
  • 此处就不用再加上任何附加指令了其实直接就和正常的使用gcc一样(能写成gcc code.c)
  • 指令:gcc code.o -o code(一般是自动生成a.out可执行程序)
  • 当把目标文件和库连接后就能生成可执行程序了

附:

对于上面形成预处理、编译、汇编的附加指令我们可以快速记忆:

在我们键盘的左上角的 ESC 就分别对应着了预处理、编译、汇编

后缀名可:i就正常记忆,s与附加指令一样,o用obj对应来记忆


2.1.5 库

在链接中就是将目标文件和库进行链接,所以在学习链接的过程就必须要了解一下库

库:

库是一个为我们提供库函数的实现的地方(在C语言中就是C语言标准库 , 本质还是一个文件,文件内有库函数的实现方法,所以对应着就有路径,Linux下是:/usr/lib64/libc.so

库分为静态库、动态库:

在Linux下:.so(动态库) 、 .a(静态库)

在windows下: .dll(动态库)、.lib(静态库)

在Linux下库有自己的命名规则:lib name .so .xxx(其中name是库的名字,而xxx是不同版本。如:libc.so 此时去掉lib 和 .so 那么就能看出来他是一个c的库 )


综上所述:

库中是函数的实现,而头文件中就是函数的声明,所以我们需要先定义头文件,然后光写了头文件还不行还需要链接上库,才能让库函数正常的使用:即:头文件+库文件+自己写的源文件 才能生成 ==》可执行程序 (而链接的目的就是于此gcc将目标文件和c的库链接起来)


2.1.6目标文件(.o)和库是如何链接的?

  1. 动态链接
    1. 可执行程序通过编译器,找到动态库(共享库)进行链接
    2. 而动态库是不能缺失当,一旦缺失就会影响所用可执行程序
  2. 静态链接
    1. 静态库在链接的时候会将自己的方法拷贝到目标程序中,也就是即使后面静态库缺失也并不会影响到已经链接过的程序了

附: ldd指令 是一个可以查看可执行程序依赖的动态库:

用法如下:

此时就能看到code是依赖于c动态库的(libc.so.6)


静态库一般来说是没有安装的,所以需要先安装一下:

  1. sudo yum install -y glibc-static(c的静态库)
  2. sudo yum install -y libstdc++-static(c++的静态库)

用静态库链接的方法附加指令 -static):gcc code.c -o code-static  -static 

如下:

此时比较动态库和静态库链接的区别:很明显用静态库的其大小会比用动态库的大许多(因为会将静态库中的内容拷贝到文件中)

附:

对于gcc来说,他的链接其实是分先后的

  1. 他会优先链接动态库,当没有动态库时才会去链接静态库
  2. -static是改变gcc的优先级让gcc优先链接静态库(对于gcc来说他的链接可能是混合由多种动静态库组成,但注意当加上-static后就会让gcc只适配静态库)

附:file指令 能查看程序是动态链接还是静态链接的


2.1.7动静态链接的优缺点:

链接动态库:

  1. 优点:
    1. 节省空间(磁盘空间、内存空间、网络空间)
  2. 缺点:
    1. 一旦动态库有点缺失,就会导致多文件无法正常使用

链接静态库:

  1. 优点:
    1. 不依赖于库,程序能独立运行
  2. 缺点
    1. 体积大,消耗资源多

3.debug、release

  • 在vs环境下就已经大概讲过,debug下的文件中添加了debug信息是可调试的、而release是发布版本进行了将调试信息优化了无法进行调试,对此debug文件就会比release文件大。
  • 在Linux下默认生成的可执行程序是一个release版本的
  • 若想生成debug调试版本的,可以在使用 gcc时加上 附加指令 -g

附加指令:readelf -S  可执行程序  查看可执行程序的空间布局情况以及一些数据的信息情况

对此上面的所有的 gcc的使用方法已讲完 他们都能直接替换成 g++ 用法是完全一样的就不过多赘述了

本章完。预知后事如何,暂听下回分解。

如果有任何问题欢迎讨论哈!

如果觉得这篇文章对你有所帮助的话点点赞吧!

持续更新大量Linux细致内容,早关注不迷路。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/635595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.30 守护进程(1) 2.31 守护进程(2)

2.30 守护进程&#xff08;1&#xff09; 终端 echo $$//查看当前终端的的pid tty//查看当前终端设备控制终端可以操作某一个进程。 进程组 会话 进程组、会话、控制终端之间的关系 find/2 查看2重定向到dev/null设备上&#xff0c;|管道&#xff08;创建子进程&#xff09…

RK3588平台开发系列讲解(USB篇)USB Device端口组合配置过程

文章目录 一、configfs二、configfs 配置过程2.1、使能相关的宏2.2、挂载configfs2.3、创建名为g1的usb复合设备2.4、配置PID和VID2.5、创建并配置strings子目录2.6、创建configuration和字符串2.7、创建functions2.8、将functions和configuration关联起来2.9、绑定到UDC,使能…

数据的存储练习题 -- (解题思路+代码)

目录 前言 知识补充 有符号和无符号的区别 练习一 练习二 练习三 练习四 练习五 练习六 练习七 前言 书接上回&#xff0c;我们学习了整形数据在内存中是怎么存储的。本篇我们就利用这些知识来做一些练习题目&#xff0c;把这些知识很好的消化掉。 知识补充 对…

简单的TCP网络程序·单进程

目录 文件1&#xff1a;tcpServer.cc 文件2&#xff1a;tcpServer.hpp 1.提出日志概念 -- 在后续完善 日志格式 -- 暂定简单的打印功能 2.创建套接字 SOCK_STREAM -- socket参数 3.bind自己的套接字 4.设置socket 为监听状态 * 新接口1&#xff1a;listen 函数1&…

IIC协议总结

IIC&#xff08;Inter-Integrated Circuit) &#xff0c;简单说就是IC&#xff08;芯片&#xff09;之间通信的总线。所谓总线&#xff0c;就是各个器件都并联到一组公共的线路上&#xff0c;然后共用这条线路来传输数据。总线的英文名为BUS&#xff0c;这是个形象的名字&#…

chatgpt赋能python:Python如何取三位数的每一位

Python如何取三位数的每一位 作为一门广泛应用的编程语言&#xff0c;Python在数值相关处理方面也十分得心应手。取三位数的每一位是一个常见的需求&#xff0c;那么在Python中该如何实现呢&#xff1f; 1. 数字字符串切片 Python中的字符串有索引和切片功能&#xff0c;我们…

chatgpt赋能python:Python如何命名输出图片名字

Python 如何命名输出图片名字 Python 是一种非常流行的编程语言。它非常灵活&#xff0c;可以用于各种应用场景。其中一个应用是图像处理。在 Python 中&#xff0c;我们可以使用不同的库来读取和处理图像。但是&#xff0c;当处理大量图片时&#xff0c;给每个图片命名会变得…

UDS关于0x37服务退出传输学习笔记

1.服务说明 客户端使用此服务来终止客户端和服务器之间的数据传输&#xff08;上传或下载&#xff09;。 2.请求消息 2.1请求消息子功能参数$Level&#xff08;LEV_&#xff09;定义 此服务不使用子函数参数。 2.2请求消息数据参数定义 transferRequestParameterRecord&a…

C++技能 - 详解const的几种使用【再也不迷糊了,干货还是蛮多的】

系列文章目录 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 C技能系列 期待你的关注哦&#xff01;&#xff01;&#xff01; 生活就是上帝发给你的一张手牌&#xff0c;无论多烂&#xff0c;你都得拿着。 Life is god give you a hand, no matter ho…

RK3588平台开发系列讲解(以太网篇)MDIO底层驱动

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、mdiobus总线二、mdiobus的注册沉淀、分享、成长,让自己和他人都能有所收获!😄 一、mdiobus总线 mdio bus是mdio管里phy寄存器的总线,此总线非设备驱动模型之总线。mdiobus在内核中用mii_bus结构体描述,mii_b…

基于51单片机的电子钟Protues仿真设计

一、设计背景 电子钟是指利用数字电路或单片机等现代电子技术来实现时间计量和显示的钟表。相较于传统机械钟、石英钟等时钟&#xff0c;电子钟具有精度高、音响小、易于制造和调节等优点&#xff0c;同时也由于其美观大方的外观设计而成为了家居装饰中不可或缺的一部分。 其…

初探react中使用MongoDB

MongoDB介绍与安装 什么是MongoDB 来自于英文单词“Humongous”&#xff0c;中文含义表示“庞大”面向文档存储的开源数据库由C编写&#xff0c;支持多种语言连接 为什么要用MongoDB 性能好&#xff08;内存计算&#xff09;大规模数据存储&#xff08;可拓展性&#xff09…

Cracking C++(9): 编译选项的设置

文章目录 1. 目的2. 生成 hello 可执行程序的过程3. 编译选项4. overlook 项目简介4.1 基本用法4.2 典型例子&#xff1a; 函数缺少返回值 1. 目的 对应到 hackingcpp 网站上 Hello World 这一节内容的笔记和个人的拓展。 2. 生成 hello 可执行程序的过程 #include <iost…

牛客网专项练习——C语言错题集(3)

文章目录 函数的缺省返回值类型找不同数组指针 函数指针const 与 指针函数里操作外面传进来的数组 函数的缺省返回值类型 “在C语言中&#xff0c;凡不加返回值类型限定的函数&#xff0c;就会被编译器作为返回整型值处理。” 这是初学学 C 语言时有接触到的一个概念&#xf…

RK3588平台开发系列讲解(进程篇)进程task_struct结构体详解(一)

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、任务 ID二、信号处理三、任务状态四、进程调度沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 Linux 里面,无论是进程,还是线程,到了内核里面,我们统一都叫任务(Task),由一个统一的结构 task_stru…

1.uniapp可视化操作-diygw

DAY1-uniapp可视化操作:DIY可视化-拖拽设计1天搞定主流小程序环境安装 文章目录 DAY1-uniapp可视化操作:DIY可视化-拖拽设计1天搞定主流小程序环境安装前言一、DIY可视化桌面客户端安装:二、小皮管理面板phpstudy(或者宝塔桌面)三、phpstorm开发工具:四、Vs Code安装:五、hbuil…

《Java Web轻量级整合开发入门》学习笔记

轻量级Java Web整合开发 第一章 轻量级Java Web开发概述 1.2 java web 开发概述 1.JSP是一种编译执行的前台页面技术。对于每个JSP页面&#xff0c;Web服务器都会生成一个相应的Java文件&#xff0c;然后再编译该Java文件&#xff0c;生成相应的Class类型文件。在客户端访问到…

chatgpt赋能python:Python怎么合并字典

Python怎么合并字典 在Python编程中&#xff0c;字典是一种非常有用的数据结构。它由一组键值对组成&#xff0c;每个键值对都是一个键和对应的值。有时候&#xff0c;我们需要将两个或多个字典合并为一个大的字典。本文将介绍Python中合并字典的方法。 方法一&#xff1a;使…

[架构之路-212]- 需求- UML需求建模:用例图、ER图/概念类图、流程图、序列图、状态机图

目录 前言&#xff1a; 什么是需求建模 1. 用例图 1.1 用例图 1.1.1 组件 1.1.2 用例细化与用例关系 1.2 用例规约 2. ER图/概念类图 3. 跨角色流程图&#xff08;串行、协同&#xff09; 4. 活动图&#xff08;并行、协同&#xff09; 5. 状态机图 6. 时序图 前言…

Letcode经典黄题——三数之和

还是那句话&#xff0c;一个题思路很重要&#xff0c;没有思路等于无头苍蝇乱撞 题目要求&#xff1a;给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 …