编译器gcc/g++ --【Linux基础开发工具】

文章目录

  • 一、背景知识
  • 二、gcc编译选项
    • 1、预处理(进行宏替换)
    • 2、编译(生成汇编)
    • 3、汇编(生成机器可识别代码)
    • 4、链接(生成可执行文件或库文件)
  • 三、动态链接和静态链接
  • 四、静态库和动态库
    • 1、动静态库
    • 2、编译器自举
      • 自举的基本步骤
  • 五、gcc其他常用选项 - 了解即可

一、背景知识

  1. 预处理(进行宏替换/去注释/条件编译/头文件展开等)
  2. 编译(生成汇编)
  3. 汇编(生成机器可识别代码)
  4. 连接(生成可执行文件或库文件)

二、gcc编译选项

格式 gcc [选项] 要编译的文件 [选项] [目标文件]

1、预处理(进行宏替换)

• 预处理功能主要包括: 宏定义,文件包含,条件编译,去注释等。

• 预处理指令是以 # 号开头的代码行。

• 实例: gcc –E hello.c –o hello.i

• 选项 “-E” ,该选项的作用是让 gcc 在预处理结束后停止编译过程。

• 选项 “-o” 是指目标文件, “.i” 文件为已经过预处理的C原始程序。

2、编译(生成汇编)

• 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后, gcc 把代码翻译成汇编语言。

• 用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。

• 实例: gcc –S hello.i –o hello.s

3、汇编(生成机器可识别代码)

• 汇编阶段是把编译阶段生成的“.s”文件转成目标文件

• 读者在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了

• 实例: gcc –c hello.s –o hello.o

4、链接(生成可执行文件或库文件)

• 在成功编译之后,就进入了链接阶段。

• 实例: gcc hello.o –o hello

三、动态链接和静态链接

在我们的实际开发中,不可能将所有代码放在一个源文件中,所以会出现多个源文件,而且多个源文件之间不是独立的,而会存在多种依赖关系,如一个源文件可能要调用另一个源文件中定义的函数,但是每个源文件都是独立编译的,即每个*.c文件会形成一个*.o文件,为了满足前面说的依赖关系,则需要将这些源文件产生的目标文件进行链接,从而形成一个可以执行的程序。这个链接的过程就是静态链接

静态链接的缺点很明显:
• 浪费空间:因为每个可执行程序中对所有需要的目标文件都要有一份副本,所以如果多个程序对同一个目标文件都有依赖,如多个程序中都调用了printf()函数,则这多个程序中都含有printf.o,所以同一个目标文件都在内存存在多个副本;
• 更新比较困难:因为每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序。但是静态链接的优点就是,在可执行程序中已经具备了所有执行程序所需要的任何东西,在执行的时候运行速度快。

动态链接的出现解决了静态链接中提到问题。动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。

动态链接其实远比静态链接要常用得多。比如我们查看下 hello 这个可执行程序依赖的动态库,会发现它就用到了一个c动态链接库:

$ ldd hellolinux-vdso.so.1 => (0x00007fffeb1ab000) libc.so.6 => /lib64/libc.so.6 (0x00007ff776af5000) /lib64/ld-linux-x86-64.so.2 (0x00007ff776ec3000)
# ldd命令用于打印程序或者库文件所依赖的共享库列表。

在这 里涉及到一个重要的概念: 库
• 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪 里实“printf”函数的呢?

• 最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用

四、静态库和动态库

1、动静态库

• 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”

• 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。 gcc hello.o –o hello

• gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证。

📌 注意:
• Linux下,动态库XXX.so, 静态库XXX.a
• Windows下,动态库XXX.dll, 静态库XXX.lib

一般我们的云服务器,C/C++的静态库并没有安装,可以采用如下方法安装

# Centos
yum install glibc-static libstdc++-static -y
#ubuntu(apt)

2、编译器自举

编译器自举(Bootstrapping)是指通过现有的编译工具来构建新的编译器的过程,尤其是指用目标语言本身编写的新编译器。这个过程的核心思想在于“自我宿主”——即一个高级语言程序可以用来编译其自身的源代码。

自举的基本步骤

  1. 初始阶段:从零开始创建一个小规模、功能有限的编译器版本A0。它可以将一小部分核心语法结构翻译为目标机器码或其他中间表示形式。

  2. 迭代改进:利用现有编译器(可能是手工编写的简单解释器或者是另一种成熟语言提供的编译系统),把更复杂的特性逐步加入到新编译器中,并能够处理更多的语言特性和优化技术。此时会产生一个新的编译器版本A1。

  3. 循环增强:随着每一轮迭代,编译器的功能越来越强大,直到它能完全理解和转换整个预期的目标语言为止。最终得到的就是全功能版的编译器An,而该编译器已经可以用自身生成的二进制文件来进行后续更新和发展了。

  4. 验证一致性:为了保证质量,在每次升级过程中都需要进行严格的测试,确保每个新版本都能正确解析并编译旧版本所支持的所有合法输入。

  5. 独立运行:一旦成功完成所有轮次的迭代并且经过充分调试之后,就可以移除对原始辅助编译环境的需求,使得最终产物成为一个独立运作的产品。

实际案例
许多现代编程语言都是采用这种方式发展的,例如GCC (GNU Compiler Collection) 的开发就是基于C/C++本身的;还有像Python这样的脚本语言也经历了类似的发展路径,其中CPython实现了Python标准库以及解释器的主要组成部分。

五、gcc其他常用选项 - 了解即可

• -E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件 里面
• -S 编译到汇编语言不进行汇编和链接
• -c 编译到目标代码
• -o 文件输出到 文件
• -static 此选项对生成的文件采用静态链接
• -g 生成调试信息。GNU 调试器可利用该信息。
• -shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
• -O0
• -O1
• -O2
• -O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
• -w 不生成任何警告信息。
• -Wall 生成所有警告信息。

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

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

相关文章

Java 注解与元数据

Java学习资料 Java学习资料 Java学习资料 一、引言 在 Java 编程中,注解(Annotation)和元数据(Metadata)是两个重要的概念。注解为程序提供了一种在代码中嵌入额外信息的方式,这些额外信息就是元数据。元…

操作系统指定用户密码永不过期

背景 实际生产环境中,数据中心操作系统通常会有基线要求(比如等保之类),要求设置操作系统密码有效期,但是infra团队或者操作系统管理员或者某些业务配置使用的操作系统用户又需要密码不能不停修改(或者说一…

无用的知识又增加了:is_assignable means?

std::pair的默认operator被delete掉了,取而代之的是两个enable_if版本。 为什么这么设计,我的理解是在std::map里,已经保存的元素的key值是不能被修改的,比如 注意,下面的代码会修改key值,编译时出现错误…

能量提升法三:赞美

前情回顾: 《能量提升法二:感恩》 片段:“感恩,就像是在跟世界说:谢谢你,我收到了,我很喜欢,请多来点” 把它归还人海,就当作每一个人,都有可能是曾经帮助…

25美赛ABCDEF题详细建模过程+可视化图表+参考论文+写作模版+数据预处理

详情见该链接!!!!!! 25美国大学生数学建模如何准备!!!!!-CSDN博客文章浏览阅读791次,点赞13次,收藏7次。通过了解比赛基本…

2025企业繁体镜像站镜像站群版 | 干扰码+拼音插入

技术背景 高效的SEO优化和内容采集是企业站群系统的核心竞争力。本文将详细介绍一套企业级网站镜像工具包,重点展示其在SEO优化、内容采集、智能处理等方面的创新实现。 系统特性 1. SEO优化功能 关键词智能布局标题标签优化链接结构优化移动端适配页面加速优化…

动态规划<九>两个数组的dp

目录 引例 LeetCode经典OJ题 1.第一题 2.第二题 3.第三题 4.第四题 5.第五题 6.第六题 7.第七题 引例 OJ传送门LeetCode<1143>最长公共子序列 画图分析&#xff1a; 使用动态规划解决 1.状态表示 ------经验题目要求 经验为选取第一个字符串的[0,i]区间以及第二个字…

大数据学习之SCALA分布式语言三

7.集合类 111.可变set一 112.可变set二 113.不可变MAP集合一 114.不可变MAP集合二 115.不可变MAP集合三 116.可变map一 package com . itbaizhan . chapter07 //TODO 2. 使用 mutable.Map 前导入如下包 import scala . collection . mutable // 可变 Map 集合 object Ma…

MongoDB中常用的几种高可用技术方案及优缺点

MongoDB 的高可用性方案主要依赖于其内置的 副本集 (Replica Set) 和 Sharding 机制。下面是一些常见的高可用性技术方案&#xff1a; 1. 副本集 (Replica Set) 副本集是 MongoDB 提供的主要高可用性解决方案&#xff0c;确保数据在多个节点之间的冗余存储和自动故障恢复。副…

基于OSAL的嵌入式裸机事件驱动框架——整体架构调度机制

参考B站up主【架构分析】嵌入式祼机事件驱动框架 感谢大佬分享 任务ID &#xff1a; TASK_XXX TASK_XXX 在系统中每个任务的ID是唯一的&#xff0c;范围是 0 to 0xFFFE&#xff0c;0xFFFF保留为SYS_TSK_INIT。 同时任务ID的大小也充当任务调度的优先级&#xff0c;ID越大&#…

WGCLOUD运维工具从入门到精通 - 如何设置主题背景

需要升级到WGCLOUD的v3.5.7或者以上版本&#xff0c;才会支持自定义设置主题背景色 WGCLOUD下载&#xff1a;www.wgstart.com 我们登录后&#xff0c;在右上角点击如下的小图标&#xff0c;就可以设置主题背景色了&#xff0c;包括&#xff1a;经典白&#xff08;默认&#x…

LigerUI在MVC模式下的响应原则

LigerUI是基于jQuery的UI框架&#xff0c;故他也是遵守jQuery的开发模式&#xff0c;但是也具有其特色的侦听函数&#xff0c;那么当LigerUI作为View层的时候&#xff0c;他所发送后端的必然是表单的数据&#xff0c;在此我们以俩个div为例&#xff1a; {Layout "~/View…

基于RIP的MGRE VPN综合实验

实验拓扑 实验需求 1、R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;其所有地址均配为公有IP地址&#xff1b; 2、R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证方&#xff1b; R2与R5之间使用ppp的CHAP认证&#xff0c;R5为主认证方&#xff1b; R3与R5之间使用HDLC封…

git的理解与使用

本地的git git除了最经典的add commit push用来做版本管理&#xff0c;其实他的分支管理也非常强大 可以说你学好了分支管理&#xff0c;就可以完成团队的配合协作了 git仓库 我们可以使用git init来初始化一个git仓库&#xff0c;只要能看见.git文件夹&#xff0c;就代表这…

Java 编程初体验

Java学习资料 Java学习资料 Java学习资料 一、引言 在当今数字化的时代&#xff0c;编程已然成为一项极具价值的技能。而 Java 作为一门广泛应用于企业级开发、移动应用、大数据等众多领域的编程语言&#xff0c;吸引着无数初学者投身其中。当我们初次踏入 Java 编程的世界&…

STM32 对射式红外传感器配置

这次用的是STM32F103的开发板&#xff08;这里面的exti.c文件没有how to use this driver 配置说明&#xff09; 对射式红外传感器 由一个红外发光二极管和NPN光电三极管组成&#xff0c;M3固定安装孔&#xff0c;有输出状态指示灯&#xff0c;输出高电平灯灭&#xff0c;输出…

https数字签名手动验签

以bing.com 为例 1. CA 层级的基本概念 CA 层级是一种树状结构&#xff0c;由多个层级的 CA 组成。每个 CA 负责为其下一层级的实体&#xff08;如子 CA 或终端实体&#xff09;颁发证书。层级结构的顶端是 根 CA&#xff08;Root CA&#xff09;&#xff0c;它是整个 PKI 体…

【自然语言处理(NLP)】深度循环神经网络(Deep Recurrent Neural Network,DRNN)原理和实现

文章目录 介绍深度循环神经网络&#xff08;DRNN&#xff09;原理和实现结构特点工作原理符号含义公式含义 应用领域优势与挑战DRNN 代码实现 个人主页&#xff1a;道友老李 欢迎加入社区&#xff1a;道友老李的学习社区 介绍 **自然语言处理&#xff08;Natural Language Pr…

Niagara学习笔记

橙色 发射器 , 绿色 粒子, 红色 渲染器 Emitter State 发射器状态 Life Cycle Mode&#xff08;生命周期模式&#xff09; 选择Self就是发射器自身管理生命周期 Loop Behavior 决定粒子发射次数 一次&#xff08;Once&#xff09;&#xff1a;发射器只播放一次多次&#…

17 一个高并发的系统架构如何设计

高并发系统的理解 第一:我们设计高并发系统的前提是该系统要高可用&#xff0c;起码整体上的高可用。 第二:高并发系统需要面对很大的流量冲击&#xff0c;包括瞬时的流量和黑客攻击等 第三:高并发系统常见的需要考虑的问题&#xff0c;如内存不足的问题&#xff0c;服务抖动的…