GCC编译器编译C/C++程序(一步完成、分步完成)
以下内容源于C语言中文网的学习与整理,非原创,如有侵权请告知删除。
参考内容
(1)GCC 预处理器选项_dllbl的博客-CSDN博客
(2)Preprocessor Options (Using the GNU Compiler Collection (GCC))
一、编译的流程
编译C/C++ 程序,是指将C/C++源代码转变为可执行程序。
这需要经历4个过程:预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)、链接(Linking)。
二、一步完成编译
1、一步完成编译的方法
GCC 编译器并未提供给用户可用鼠标点击的界面窗口,要想调用 GCC 编译器编译 C 或者 C++ 程序,只能通过执行相应的 gcc 或者 g++ 指令。使用 GCC 编译器编译 C 或者 C++ 程序,也必须要经历上述的 4 个过程。但考虑在实际使用中,用户可能并不关心程序的执行结果,只想快速得到最终的可执行程序,因此 gcc 和 g++ 都对此需求做了支持。
如下所示,运行C文件demo.c与C++文件demo.cpp的一步完成编译的指令,GCC 编译器就会在当前目录下生成对应的可执行文件,该文件的名称为 a.out,或者使用-o 选项指定要生成的文件名。
xjh@ubuntu:~/iot/tmp$ gcc demo.c
xjh@ubuntu:~/iot/tmp$ g++ demo.cpp #或者 gcc -xc++ -lstdc++ -shared-libgcc demo.cpp
xjh@ubuntu:~/iot/tmp$ gcc demo.c -o demo.exe
xjh@ubuntu:~/iot/tmp$ g++ demo.cpp -o democpp.exe # 或者 gcc -xc++ -lstdc++ -shared-libgcc demo.cpp -o democpp.exe
虽然仅有一条指令,但依然按照预处理、编译、汇编、链接的过程将 C 、C++ 程序转变为可执行程序的。
2、如何保留中间文件
那些本应在预处理阶段、编译阶段、汇编阶段生成的中间文件,上述执行方式默认是不会生成的,只会生成最终的 a.out 可执行文件,除非为 gcc 或者 g++ 额外添加 -save-temps 选项。
xjh@ubuntu:~/iot/tmp$ ls
demo.c
xjh@ubuntu:~/iot/tmp$ gcc demo.c
xjh@ubuntu:~/iot/tmp$ ls
a.out demo.c
xjh@ubuntu:~/iot/tmp$ gcc demo.c -save-temps
xjh@ubuntu:~/iot/tmp$ ls
a.out demo.c demo.i demo.o demo.s
xjh@ubuntu:~/iot/tmp$
三、分步编译程序
表1列出了实际使用 gcc 或者 g++ 指令编译 C/C++ 程序时,常用的一些指令选项。
gcc/g++指令选项 | 功 能 |
---|---|
-E | 预处理指定的源文件,不进行编译。 |
-S | 编译指定的源文件,不进行汇编。 |
-c | 编译、汇编指定的源文件,不进行链接。 |
-o | 指定生成文件的文件名。 |
-llibrary 或 -I library | 其中 library 表示要搜索的库文件的名称。该选项用于手动指定链接环节中程序可以调用的库文件。建议 -l 和库文件名之间不使用空格,比如 -lstdc++。 |
-L/pathname | 该选项用于为GCC添加另一个搜索链接库的目录,其中pathname是链接库的路径。 |
-ansi | 对于 C 语言程序来说,其等价于 -std=c90;对于 C++ 程序来说,其等价于 -std=c++98。 |
-std= | 手动指令编程语言所遵循的标准,例如 c89、c90、c++98、c++11 等。 |
下面将以某个demo.cpp 源文件来说明如何分步编译一个C++程序。
1、预处理
(1)通过给 g++ 指令添加 -E 选项,可实现令 GCC 编译器只对目标源程序进行预处理操作。
(2)预处理,其实就是对各种预处理命令进行处理,包括头文件的包含、宏定义的扩展、条件编译的选择、去掉空行与注释等等。
- 将所有的
#define
删除,并展开所有的宏定义。 - 处理所有条件编译命令,比如 #if、#ifdef、#elif、#else、#endif 等。
- 处理
#include
命令,将被包含文件的内容插入到该命令所在的位置,这与复制粘贴的效果一样。注意,这个过程是递归进行的,也就是说被包含的文件可能还会包含其他的文件。 - 删除所有的注释
//
和/* ... */
。 - 添加行号和文件名标识,便于在调试和出错时给出具体的代码位置。
- 保留所有的
#pragma
命令,因为编译器需要使用它们。
Linux系统中,通常用 ".i" 或者 ".ii" 作为 C++ 程序预处理后所得文件的后缀名。当你无法判断宏定义是否正确,或者文件包含是否有效时,可以查看
.i
文件来确定问题。
(3)默认情况下 g++ -E 指令只会将预处理操作的结果输出到屏幕上,并不会自动保存到某个文件。因此该指令往往会和 -o 选项连用,将结果导入到指令的文件中,如下所示。
xjh@ubuntu:~/iot/tmp$ ls
demo.cpp
xjh@ubuntu:~/iot/tmp$ g++ -E demo.cpp -o demo.i
xjh@ubuntu:~/iot/tmp$ ls
demo.cpp demo.i
xjh@ubuntu:~/iot/tmp$
(4)使用“g++ -E ”表示只进行预处理操作,在此基础上我们还可以加上其他参数选项。相关介绍见参考内容(1)(2)。
选项 | 功能 |
-C(大写字母) | 阻止GCC删除源文件和头文件中的注释 |
-include file | 如同在源代码中添加 #include "file" 一样。 |
…… | …… |
-dM | 告诉预处理器输出有效的宏定义列表 ( 预处理结束时仍然有效的宏定义 ) |
2、编译
(1)通过给 g++ 指令添加 -S 选项,即可令 GCC 编译器仅对指定预处理文件做编译操作。
(2)编译,其实就是将预处理得到的程序代码,经过一系列的词法分析、语法分析、语义分析以及优化,生成为当前机器支持的汇编代码文件(Linux 发行版通常以 ".s" 作为其后缀名)。
(3)即便没有 -o 选项,编译结果也会输出到和预处理文件同名(后缀名改为 .s)的新建文件中。
xjh@ubuntu:~/iot/tmp$ g++ -S demo.i
xjh@ubuntu:~/iot/tmp$ ls
demo.cpp demo.i demo.s
xjh@ubuntu:~/iot/tmp$
(4)使用“g++ -S”时,-S 选项只是表明让 GCC 编译器将指定文件处理至编译阶段结束,操作的文件不一定是经过预处理后得到的 .i 文件,也可以是源代码文件。如果操作对象为 .i 文件,则 GCC 编译器只需编译此文件;如果操作对象为 .c 或者 .cpp 源代码文件,则 GCC 编译器会对其进行预处理和编译这 2 步操作。
(5)在“g++ -S”基础上,如果想提高文件内汇编代码的可读性,可以借助 -fverbose-asm 选项,GCC 编译器会自行为汇编代码添加必要的注释,
xjh@ubuntu:~/iot/tmp$ g++ -S -fverbose-asm demo.i
xjh@ubuntu:~/iot/tmp$ ls
demo.cpp demo.i demo.s
xjh@ubuntu:~/iot/tmp$
3、汇编
(1)通过给 g++ 指令添加 -c 选项,即可令 GCC 编译器仅对指定的汇编代码文件做汇编操作。
(2)汇编阶段就是将之前生成的汇编代码文件(demo.s)做进一步转换,生成对应的机器指令。大部分汇编语句对应一条机器指令,有的汇编语句对应多条机器指令。相对于编译操作,汇编过程会简单很多,它并没有复杂的语法,也没有语义,也不需要做指令优化,只需要根据汇编语句和机器指令的对照表一一翻译即可。
(3)默认情况下汇编操作会自动生成一个和汇编代码文件名称相同、后缀名为 .o 的二进制文件(又称为目标文件)。
xjh@ubuntu:~/iot/tmp$ g++ -c demo.s
xjh@ubuntu:~/iot/tmp$ ls
demo.cpp demo.i demo.o demo.s
xjh@ubuntu:~/iot/tmp$
(4)和 g++ -S 类似,g++ -c 选项并非只能用于加工 .s 文件。事实上,-c 选项只是令 GCC 编译器将指定文件加工至汇编阶段,但不执行链接操作。这也就意味着:
- 如果指定文件为源程序文件(例如 demo.cpp),则 g++ -c 指令会对 demo.cpp 文件执行预处理、编译以及汇编这 3 步操作;
- 如果指定文件为刚刚经过预处理后的文件(例如 demo.i),则 g++ -c 指令对 demo.i 文件执行编译和汇编这 2 步操作;
- 如果指定文件为刚刚经过编译后的文件(例如 demo.s),则 g++ -c 指令只对 demo.s 文件执行汇编这 1 步操作。
- 如果指定文件已经经过汇编,或者 GCC 编译器无法识别,则 g++ -c 指令不做任何操作。
4、链接
(1)目标文件已经是二进制文件,与可执行文件的组织形式类似,只是有些函数和全局变量的地址还未找到,因此还无法执行。链接器的作用就是找到这些目标地址,将所有的目标文件组织成一个可以执行的二进制文件。它必须把符号(变量名、函数名等一些列标识符)用对应的数据的内存地址(变量地址、函数地址等)替代,以完成程序中多个模块的外部引用。
(2)另外,链接器也必须将程序中所用到的所有C标准库函数加入其中。对于链接器而言,链接库不过是一个具有许多目标文件的集合,它们在一个文件中以方便处理。
标准库的大部分函数通常放在文件 libc.a 中(文件名后缀.a代表“achieve”,译为“获取”),或者放在用于共享的动态链接文件 libc.so 中(文件名后缀.so代表“share object”,译为“共享对象”)。这些链接库一般位于 /lib/ 或 /usr/lib/,或者位于 GCC 默认搜索的其他目录。 当使用 GCC 编译和链接程序时,GCC 默认会链接 libc.a 或者 libc.so,但是对于其他的库(例如非标准库、第三方库等),就需要手动添加。
(3)如何实现链接操作?
只要将汇编阶段得到的 demo.o 作为参数传递给g++,g++ 会根据所给文件的后缀名 .o,自行判断出此类文件为目标文件,仅需要进行链接操作,g++就会在其基础上完成链接操作(GCC默认会链接 libc.a 或者 libc.so,但是对于其他的库,例如非标准库、第三方库等,就需要手动添加)。
如果不使用 -o 选项将执行结果输出到指定文件,则默认创建一个名为 a.out 的可执行文件,并将执行结果输出到该文件中。
xjh@ubuntu:~/iot/tmp$ g++ demo.o
xjh@ubuntu:~/iot/tmp$ ls
a.out demo.cpp demo.i demo.o demo.s
xjh@ubuntu:~/iot/tmp$ g++ demo.o -o demo.exe
xjh@ubuntu:~/iot/tmp$ ls
a.out demo.cpp demo.exe demo.i demo.o demo.s
xjh@ubuntu:~/iot/tmp$
相关文章:

GCC编译器编译C/C++程序(一步完成、分步完成)
以下内容源于C语言中文网的学习与整理,非原创,如有侵权请告知删除。 参考内容 (1)GCC 预处理器选项_dllbl的博客-CSDN博客 (2)Preprocessor Options (Using the GNU Compiler Collection (GCC)) 一、编译的…...
Java8中那些方便又实用的Map函数
简介 java8之后,常用的Map接口中添加了一些非常实用的函数,可以大大简化一些特定场景的代码编写,提升代码可读性,一起来看看吧。 computeIfAbsent函数 比如,很多时候我们需要对数据进行分组,变成Map<…...

如何修复dxgi.dll文件错误?修复方法推荐
如果您使用Windows操作系统,在使用某些应用程序时,可能会遇到dxgi.dll文件错误。这可能会导致应用程序崩溃或无法正常运行。在本文中,我们将探讨如何修复dxgi.dll文件错误。 一.什么是dxgi.dll文件 dxgi.dll文件是Microsoft DirectX图形接口…...

数字化时代,你应该知道的BI
我曾经看到有人在讨论过商业智能BI的部署对于企业是否有实际意义,现在市场的数据已经证明商业智能BI在商业世界中,在企业的实践中证明了自己的价值,得到了广泛的认可。 一、什么是BI 有一点可能很多人没有想到,实际上商业智能BI…...

前端jQuery ajax请求,后端node.js使用cors跨域
前言 跨域,一句话介绍: 你要请求的URL地址与当前的URL地址,协议不同、域名不同、端口不同时,就是跨域。 步入正题 前端,jQuery ajax请求 $.ajax({async: false,method: post,//URl和端口与后台匹配好,当…...

【最重要的 G 代码命令列表】
【最重要的 G 代码命令列表】1. 什么是G代码?2. 如何阅读G代码命令?3. 最重要/最常见的 G 代码命令3.1 G00 – 快速定位3.2 G01 – 线性插值3.3 G02 – 顺时针圆形插值3.4 G00、G01、G02 示例 – 手动 G 代码编程3.4 G03 – 逆时针圆形插补3.5 G20/ G21 …...
好用的公共DNS地址共享
公共DNS服务器地址大全 服务商云公共DNS服务器IP大全114DNS114.114.114.114114.114.115.115DNSPod DNS+119.29.29.29182.254.116.1162402:4e00::DNS 派 电信/移动/铁通101.226.4.6218.30.118.6DNS 派 联通123.125.81.6140.207.198.6cnnicDNS1.2.4.8210.2.4.82001:dc7:1000::1Go…...

C#:Krypton控件使用方法详解(第十三讲) ——kryptonDomainUpDown
今天介绍的Krypton控件中的kryptonDomainUpDown。下面介绍控件的外观属性和Item属性:Cursor属性:表示鼠标移动过该控件的时候,鼠标显示的形状。属性值如下图所示:Text属性:表示控件的显示文本内容,属性值为…...

Git设置SSH Key
一、git 配置 (1)打开 git 命令窗口 (2)配置用户名(填自己的姓名) git config --global user.name “xinyu.xia” (3)配置用户邮箱(填自己的邮箱࿰…...

WireShark如何抓包,各种协议(HTTP、ARP、ICMP)的过滤或分析,用WireShark实现TCP三次握手和四次挥手
WireShark一、开启WireShark的大门二、如何抓包 搜索关键字2.1 协议过滤2.2 IP过滤2.3 过滤端口2.4 过滤MAC地址2.5 过滤包长度2.6 HTTP模式过滤三、ARP协议分析四、WireShark之ICMP协议五、TCP三次握手与四次挥手5.1 TCP三次握手实验5.2 可视化看TCP三次握手5.3 TCP四次挥手5.…...

熬夜30天吃透这九大Java核心专题,我收割了3个大厂offer
这次一共收割了3个大厂offer,分别是蚂蚁金服、美团和网易,特意分享这次对我帮助非常大的宝典资料,一共涉及九大核心专题,分别是计算机网络、操作系统、MySQL、Linux、JAVA、JVM、Redis、消息队列与分布式、网站优化相关࿰…...

DMHS搭建DMDSC 2节点集群同步到单库
DMHS搭建DMDSC 2节点集群同步到单库环境介绍1 安装DMOCI1.1 关闭数据库实例服务1.2 将DMOCI 复制到源端与目的端的数据库bin目录1.3 对数据库bin 执行目录文件更改用户属组和权限2 启动源数据库服务并配置数据库实例参数2.1 使用DMCSSM启动集群实例2.2 DMDSC源其中一个节点执行…...
一条sql执行很慢可能的原因,如何优化
文章目录 sql怎么会变慢呢?1、大多数情况下很正常,偶尔很慢,则有如下原因2、这条 SQL 语句一直执行的很慢,则有如下原因:慢sql优化数据库中设置SQL慢查询分析慢查询日志慢sql如何让优化索引sql语句1、分页查询优化2、优化insert语句数据库结构优化优化器优化架构优化总结s…...

【设计模式】适配器模式和桥接模式
适配器模式 适配器模式 : 就是将一个类的接口变成客户端所期望的另一种接口,使得原本因为接口不匹配而无法一起工作的接口可以正常工作。属于结构型模式 比方说我有一个A牌子的奶瓶,然后买了个B牌子的奶嘴,不能匹配怎么办? 再买一个转换器…...

被隐藏的过程——预处理
文章目录0. 前言1. 程序的翻译环境和执行环境2. 被隐藏的过程2.1 翻译环境2.2 编译3.2.1 预编译3.2.2 编译2.2.3 汇编2.3 链接2.4 运行环境3. 预处理3.1 预定义符号3.2 #define3.2.1 #define定义标识符3.2.2 #define定义宏3.2.3 #define替换规则3.2.4 #和##3.2.5 带副作用的宏参…...

strace 用法介绍
strace 是什么 strace 是一个可用于诊断和调试的 Linux 用户空间跟踪器。我们用它来监控用户空间进程和内核的交互,比如系统调用、信号传递、进程状态变更等。 strace 作为一种动态跟踪工具,能够帮助我们高效地定位进程和服务故障。它像是一个侦探&…...

TiDB数据库架构概述
文章目录TiDB体系架构TiDB ServerStorage Cluster(存储引擎)PD cluster题目TiDB体系架构 TiDB Server Sql语句最先到达 TiDB Server集群 它是无状态的,数据并不是存储在这里面,当一个会话连接到TiDB Server集群上,sql语句发过来,…...
[深入理解SSD系列综述 闪存实战2.1.2] SLC、MLC、TLC、QLC、PLC NAND_固态硬盘闪存颗粒类型
闪存最小物理单位是 Cell, 一个Cell 是一个晶体管。 闪存是通过晶体管储存电子来表示信息的。在晶体管上加入了浮动栅贮存电子。数据是0或1取决于在硅底板上形成的浮动栅中是否有电子。有电子为0,无电子为1. SSD 根据闪存颗粒区分,固态硬盘有SLC、MLC、TLC、QLC、PLC 五种类型…...

游戏逆向之游戏技能分析
角色的当前技能列表往往都是从系统的技能库中进行筛选而组成的,而这个筛选的过程大多非常的复杂,经过的代码和临时结构体的传递也非常的多,所以在分析技能对象来源的时候常常要将OD和CE配合来使用。下面我们来分析下《天堂2》的技能列表。 首…...

汽车制造商与IT公司之间的技术合作案例
如果您对最新汽车技术感兴趣的话,您可能经常听到汽车制造商和IT公司正在合作开发技术的消息。汽车生产商为何自身不进行技术开发,而是与IT企业合作呢?因为最近随着以IT技术为基础的电动汽车等环保汽车或无人驾驶汽车等的登场和发展,汽车制造商单独进行技术开发需要花费很多时间…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...