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

news2024/11/26 19:51:04

目录

前言

1.看一段样例

 2.程序的翻译过程

1.第一个阶段:预处理

2.第二个阶段:编译

3.第三个阶段:汇编

4.第四个阶段:链接

3.程序的编译为什么是这个样子?

4. 关于编译器

5.链接(动静态链接)


前言

1.首先,我们来看一段样例(见一下)

2.见完之后,我们来看一下程序的翻译过程

3.了解一下翻译的过程为什么是这样的?再顺带谈一下编译器。

4.最后,我们要谈一下动静态链接,看一下它们的特点和区别


1.看一段样例

一段C语言代码:

(编译器为gcc)

在这里,可能你的编译器是不支持在循环体内直接定义变量的,因为编译器版本老旧,这时需要加上-std=99,让编译器支持C99。

在执行编译的时候可以加上-o ,在-o后面可以指定生成的可执行程序的名字。


一段C++代码:

注意C++文件的后缀为(.cc/.cpp/.cxx)

(编译器为g++)

如果没有g++,需要下载安装,下面是g++的安装指令:

yum install -y gcc-c++

在这里我们也要加上选项 -std = c++11

查看运行结果:

如果想指定c++可执行程序的名字,同样是使用-o选项

(注意:gcc不能编译c++的代码,但是g++可以编译c语言的代码)


 2.程序的翻译过程

使用C语言代码示例:

1.第一个阶段:预处理

说明:在这个阶段编译器会进行宏替换,去注释,头文件展开,条件编译

请看下面的代码:

接下来我们使用gcc的命令让程序在每个阶段都停下来,第一个选项(-E),在这里产生了临时文件test.i (-E的含义:从现在开始进行程序的编译,预处理完成,就停下)

在这里,我们发现,源代码中一下子多了八百多行代码,这就是因为<stdio.h>头文件展开拷贝到源文件,所以经过了预处理,头文件就没用了。(我们发现预处理阶段确实进行了宏的替换,去注释)

Linux系统中存在<stdio.h>的文件,才能进行此操作

Linux系统中所有的库:

关于条件编译(编译器在预处理阶段会对代码进行动态的裁剪):

        在C语言程序的预处理阶段,条件编译起着非常重要的作用。预处理阶段是在实际的编译之前进行的,主要目的是对源代码进行一些预处理操作,例如宏替换、头文件包含等。条件编译指令会在预处理阶段根据条件判断是否包含或排除特定的代码块,从而影响编译后生成的目标代码。

        使用条件编译指令可以根据不同的条件选择性地包含或排除特定的代码块。这样可以根据编译条件在不同情况下编译不同的代码,提高程序的灵活性和可移植性。

        

        我们在写条件编译的时候,一般会定义宏去调用,这样的方式效率是很低的,在Linux系统中,在指令界面就可以动态的向源代码添加宏,下面是一段示例:

在Linux中,使用gcc编译器时,可以通过 -D选项来定义预处理宏。当你使用 -D后跟一个宏名时,它告诉编译器在编译源代码之前定义该宏,可以选择性地为宏指定一个值。

        在下面这个例子中:我们为源代码中添加了宏 v1= 1 ,运行可执行程序之后,得到了接过条件编译的结果。

接着看v2 = 1


2.第二个阶段:编译

说明:编译阶段是将经过预处理后的源代码翻译成汇编代码的过程。编译器会将C语言源代码翻译成相应的汇编语言代码。

编译指令:-S表示从现在开始程序的编译,编译完成就停下来。

test.s:C语言代码转成的汇编语言代码。


3.第三个阶段:汇编

说明:汇编器会将汇编代码中的指令和数据转换成机器指令,并生成二进制目标文件。 汇编的结果是生成一个目标文件,通常以.o为扩展名。

编译指令:-c表示从现在开始进行程序的汇编,汇编完成就停下来

这个.o文件是不可执行的


4.第四个阶段:链接

说明:链接目标文件和链接库生成可执行程序(二进制的程序)。


3.程序的编译为什么是这个样子?

        在没有c语言的时候,都是用的二进制编程。三体电视剧中的机器上就是这种打孔纸带。有孔的地方信息可以透过去就是(1),没孔的地方就是(0)。但这种二进制是十分不方便的,还容易出错,这时候就发明了汇编语言,但觉得汇编语言还是不方便,后面就有了c语言。

想一想编译器是从哪里来的,二进制编程需要编译器吗?

        二进制当然是不用编译器的,从汇编开始我们就需要编译器了。编译器是非常不容易写的,我们是把c语言直接转成二进制容易,还是先转成汇编,再让汇编转成二进制容易?当然是后者比较容易,我们只需要将c语言转成汇编就行了,因为汇编转成二进制的过程前人已经帮忙做了(站在巨人的肩膀上),所以c编译器的核心工作只需要将c语言转成汇编就行了。

        因为历史选择了从二进制到汇编,从汇编到更高级的语言,从更高级的语言到c语言。我们编译的过程就是一个回溯历史的过程,这样的效率是最高的,所以c语言的编译是这个样子。


4. 关于编译器

先有语言还是语言的编译器

        当然是先有语言,才有编译器。最早的汇编语言的编译器是用二进制语言写的,汇编语言才能转成二进制跑起来。

编译器的自举

编译器的自举(bootstrapping)是指使用已经存在的编译器来编译自身的过程。简单来说,自举是通过一个较早版本的编译器来编译当前版本的编译器,从而生成一个新的、功能相同但可能更高效的编译器。 自举的过程通常涉及以下步骤:

1. **初始阶段**:在自举过程开始之前,需要有一个已经存在的编译器,通常是由其他编译器或者手动编写的汇编语言程序生成的。

2. **第一次编译**:使用初始阶段得到的编译器,将编译器的源代码编译成可执行文件。这个可执行文件就是一个新的、功能相同的编译器。

3. **第一次自举**:使用第一次编译得到的新编译器,将编译器的源代码再次编译成可执行文件。这一次编译的目标是生成一个和第一次编译得到的新编译器完全相同的新编译器。

4. **迭代自举**:重复进行自举过程,使用新生成的编译器来编译自身的源代码,生成更高效的新版本编译器。这个过程可以多次迭代,每次都会产生一个新的编译器版本,直到达到所需的性能和功能。

        通过自举,编译器可以逐步改进和优化自身,生成更高效的版本。自举的过程可以确保编译器的正确性,因为每个新版本的编译器都是由之前版本编译而来,保证了功能的一致性。

        需要注意的是,自举过程的初始阶段需要使用其他编译器或者手动编写的汇编语言程序,以便启动自举过程。自举是编译器开发和维护中重要的技术,它使得编译器可以自我改进和更新,为编程语言的发展提供了基础。


5.链接(动静态链接)

是什么?
我们的程序和库结合的过程,语言是一定要有自己的标准库的。

(安装开发环境:安装语言的标准库+头文件)

标准库通常包括各种数据结构、算法、输入输出、文件操作、网络通信等常用功能,以帮助开发人员更高效地编写程序。

在Linux中,ldd加上可执行程序,就可以查到该执行程序依赖了什么库

为什么要有链接?

1.让开发站在巨人的肩膀上 2.提高开发的效率

怎么做的?

在Linux系统中,分为两种库,动态库:.so  静态库:.a(动态链接,静态链接)

静态链接
特点:在生成可执行文件的时候(链接阶段),把所有需要的函数的二进制代码都包含到可执行文件中去。因此,链接器需要知道参与链接的目标文件需要哪些函数,同时也要知道每个目标文件都能提供什么函数,这样链接器才能知道是不是每个目标文件所需要的函数都能正确地链接。如果某个目标文件需要的函数在参与链接的目标文件中找不到的话,链接器就报错了。目标文件中有两个重要的接口来提供这些信息:一个是符号表,另外一个是重定位表。
优点:在程序发布的时候就不需要的依赖库,也就是不再需要带着库一块发布,程序可以独立执行。
缺点:程序体积会相对大一些。
如果静态库有更新的话,所有可执行文件都得重新链接才能用上新的静态库。
动态链接
特点: 在编译的时候不直接拷贝可执行代码,而是通过记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统,操作系统负责将需要的动态库加载到内存中,然后程序在运行到指定的代码时,去共享执行内存中已经加载的动态库可执行代码,最终达到运行时连接的目的。
优点: 多个程序可以共享同一段代码,而不需要在磁盘上存储多个拷贝。
缺点: 由于是运行时加载,可能会影响程序的前期执行性能。

下面是同一个程序在不同链接下的内存对比,很显然静态链接的内存大小是远大于动态链接

 

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

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

相关文章

Docker的常见命令以及命令别名

常见命令 命令说明docker pull拉取镜像docker push推送镜像到DockerRegistrydocker images查看本地镜像docker rmi删除本地镜像docker run创建并允许容器docker stop停止指定容器docker start启动指定容器docker restart重新启动容器docker rm删除指定容器docker ps查看容器do…

波奇学Linux:文件系统打开文件

从文件系统来看打开文件 计算机系统和磁盘交互的大小是4kb 物理内存的4kb&#xff0c;磁盘的4kb文件叫做页帧 磁盘数据块的以4kb为单位。 减少IO的次数&#xff0c;减少访问外设的次数--硬件 基于局部性的原理&#xff0c;预加载机制--软件 操作系统管理内存 操作系统对…

相机图像质量研究(19)常见问题总结:CMOS期间对成像的影响--Sensor Noise

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

2.13日学习打卡----初学RocketMQ(四)

2.13日学习打卡 目录&#xff1a; 2.13日学习打卡一.RocketMQ之Java ClassDefaultMQProducer类DefaultMQPushConsumer类Message类MessageExt类 二.RocketMQ 消费幂消费过程幂等消费速度慢的处理方式 三.RocketMQ 集群服务集群特点单master模式多master模式多master多Slave模式-…

使用Python生成二维码的完整指南

无边落木萧萧下&#xff0c;不如跟着可莉一起游~ 可莉将这篇博客收录在了&#xff1a;《Python》 可莉推荐的优质博主首页&#xff1a;Kevin ’ s blog 本文将介绍如何使用Python中的qrcode库来生成二维码。通过简单的代码示例和详细解释&#xff0c;读者将学习如何在Python中轻…

可变参数(c/c++)

目录 一、C语言版本 二、C的实现方法 2.1数据包 2.2sizeof...运算符 2.3可变参数模板的使用 2.4emplace_back() 有时候我们在编写函数时&#xff0c;可能不知道要传入的参数个数&#xff0c;类型 。比如我们要实现一个叠加函数&#xff0c;再比如c语言中的printf,c中的emp…

QObject 的拷贝构造和赋值操作

QObject中没有提供一个拷贝构造函数和赋值操作符给外界使用&#xff0c;其实拷贝构造和赋值的操作都是已经声明了的&#xff0c;但是它们被使用了Q_DISABLE_COPY () 宏放在了private区域。因此所有继承自QObject的类都使用这个宏声明了他们的拷贝构造函数和赋值操作符为私有。 …

算法沉淀——BFS 解决 FloodFill 算法(leetcode真题剖析)

算法沉淀——BFS 解决 FloodFill 算法 01.图像渲染02.岛屿数量03.岛屿的最大面积04.被围绕的区域 BFS&#xff08;广度优先搜索&#xff09;解决 Flood Fill 算法的基本思想是通过从起始点开始&#xff0c;逐层向外扩展&#xff0c;访问所有与起始点相连且具有相同特性&#xf…

Python六级考试笔记

Python六级考试笔记【源源老师】 六级标准 一、 掌握文件操作及数据格式化。 二、 掌握数据可视化操作。 三、 理解类与对象的概念&#xff0c;初步掌握类与对象的使用。 四、 掌握SQLite数据库基础编程。 五、 掌握简单的使用tkinter的GUI设计。 ​ 1. 文件操作 &#xff0…

深入了解社区店:定义、模式与优势

在当今的商业环境中&#xff0c;社区店正逐渐成为创业者们关注的热点。本文将以我的鲜奶吧店铺为例&#xff0c;深入探讨社区店的定义、模式和优势&#xff0c;为您提供最有价值的干货信息。 1、社区店的定义 社区店是指位于社区内或周边&#xff0c;以服务社区居民为主要目标…

shell脚本命令:mktemp和install

目录 一、mktemp命令 1、mktemp命令用法和格式 2、mktemp命令的实现原理 3、相关操作 3.1 创建临时文件或目录 3.2 指定临时文件名或目录名的后缀字符位数 3.3 指定临时文件或目录的父目录 3.4 指定临时文件或目录的后缀 4、实现文件独立的目录垃圾箱 二、install命令…

真假难辨 - Sora(OpenAI)/世界模拟器的技术报告

目录 引言技术报告汉译版英文原版 引言 Sora是OpenAI在2024年2月15日发布的世界模拟器&#xff0c;功能是通过文本可以生成一分钟的高保真视频。由于较高的视频质量&#xff0c;引起了巨大关注。下面是三个示例&#xff0c;在示例之后给出了其技术报告&#xff1a; tokyo-wal…

XMall 开源商城 SQL注入漏洞复现(CVE-2024-24112)

0x01 产品简介 XMall 开源电商商城 是开发者Exrick的一款基于SOA架构的分布式电商购物商城 前后端分离 前台商城:Vue全家桶 后台管理:Dubbo/SSM/Elasticsearch/Redis/MySQL/ActiveMQ/Shiro/Zookeeper等。 0x02 漏洞概述 XMall 开源商城 /item/list、/item/listSearch、/sys/…

2024年【广东省安全员C证第四批(专职安全生产管理人员)】考试试卷及广东省安全员C证第四批(专职安全生产管理人员)复审模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 广东省安全员C证第四批&#xff08;专职安全生产管理人员&#xff09;考试试卷是安全生产模拟考试一点通总题库中生成的一套广东省安全员C证第四批&#xff08;专职安全生产管理人员&#xff09;复审模拟考试&#xf…

【送码】【IOS付费榜92名】春节不打烊,功德加倍攒

整体效果概览图 船新玩法&#xff0c;换个姿势攒功德 竞品玩法 过于简单&#xff1a;都是敲敲&#xff0c;然后设置里换换木鱼样式、音色等 本APP玩法 功德上云&#xff1a;敲击之后&#xff0c;会将所积攒的功德上传至fo祖云端 功德可视化&#xff1a;每日功德、3D功德地…

Panalog 日志审计系统 sessiptbl.php 前台RCE漏洞复现

0x01 产品简介 Panalog是一款日志审计系统,方便用户统一集中监控、管理在网的海量设备。 0x02 漏洞概述 Panalog日志审计系统 sessiptbl.php接口处存在远程命令执行漏洞,攻击者可执行任意命令,接管服务器权限。 0x03 影响范围 version <= MARS r10p1Free 0x04 复现…

Leetcode 452. 用最少数量的箭引爆气球435. 无重叠区间

class Solution {public int findMinArrowShots(int[][] points) {Arrays.sort(points,(o1,o2)->Integer.compare(o1[0], o2[0]));int count1;//箭的数量for(int i1;i<points.length;i) {if(points[i][0]>points[i-1][1]) {count;//边界没重合&#xff0c;又需要一支箭…

【刷题记录】合并两个有序数组、移除元素

本系列博客为个人刷题思路分享&#xff0c;有需要借鉴即可。 1.题目链接&#xff1a; T1&#xff1a;LINK T2&#xff1a;LINK 2.详解思路&#xff1a; T1: 思路1&#xff1a;弄个新数组&#xff0c;比较两个数组中的值&#xff0c;哪个小就把哪个值放到新数组中。 分析1&a…

kafka如何保证消息不丢?

概述 我们知道Kafka架构如下&#xff0c;主要由 Producer、Broker、Consumer 三部分组成。一条消息从生产到消费完成这个过程&#xff0c;可以划分三个阶段&#xff0c;生产阶段、存储阶段、消费阶段。 产阶段: 在这个阶段&#xff0c;从消息在 Producer 创建出来&#xff0c;…

Godot 游戏引擎个人评价和2024年规划(无代码)

文章目录 前言Godot C# .net core 开发简单评价Godot相关网址可行性 Godot(GDScirpt) Vs CocosGodot VS UnityUnity 的裁员Unity的股票Unity的历史遗留问题&#xff1a;Mono和.net core.net core的开发者&#xff0c;微软 个人的独立游戏Steam平台分成说明独立游戏的选题美术风…