当前位置: 首页 > news >正文

Linux 编译器 gcc/g++

本文已收录至《Linux知识与编程》专栏!
作者:ARMCSKGT
演示环境:CentOS 7 

   


目录

前言

正文

gcc/g++常用命令

自定义可执行程序名命令-o

预处理指令-E

编译指令-S

汇编指令-c

链接指令gcc

命令巧记口诀

 链接库

动态库-动态链接

静态库-静态链接

动静态库对比

其他指令

声明与定义分离的编译指令

C99标准编译指令

gcc和g++的联系与区别

 最后


前言

在Windows环境下,我们我们使用VS编译器可以写代码然后运行编译代码所成的程序,但在Linux系统下,我们写的C/C++代码需要通过gcc(C语言)和g++(C++语言)编译器才能生成可执行程序,所以学习gcc和g++是非常重要的!


正文

在实际的使用中,单纯的编译执行C和C++文件gcc和g++操作几乎相同,但是内部工作原理是截然不同的!所以在后面的讲解中会以gcc为例进行讲解,g++操作与之相同!

如果您在使用时系统报错:bash: gcc(或g++): command not found,这是因为你的Linux系统没有安装gcc或g++导致的,使用命令:

yum -y install gcc //安装gcc
yum -y install g++ //安装g++

一般Linux系统是安装了gcc的,但g++需要手动安装!


gcc/g++常用命令


我们在使用中,如果想利用对应文件生成可执行程序,命令是:

gcc [-选项] [.c文件]
g++ [-选项] [.cpp文件]

如果不加(除o)的其他选项,那么默认直接生成可执行程序,程序名为a.out,我们输入命令 ./a.out 就可以执行这个程序!


自定义可执行程序名命令-o

命令:

gcc [.c文件] -o [自定义名称] //建议写法
gcc -o [自定义名称] [.c文件] //这种写法也是可以的,但是不建议

这里需要注意的是,-o选项后面紧跟的必须是自定义名称,可以想象:-o [自定义名称] 是固定组合,不能颠倒顺序乱写

g++也可以通过-o选项生成自定义名称的可执行程序!

我们都知道源文件变成可执行程序会经过四个阶段:预处理->编译->汇编->链接库,gcc/g++编译时如果不加选项是直接执行这四步,如果我们想看其中一步执行后的文件,那么就需要对应的选项。


预处理指令-E

指令:

gcc -E [.c文件] -o [文件名].i

预处理又称预编译,预处理后的文件其后缀我们默认是 .i ,而且在这里我们如果想获得预处理后的代码文件还需要指定一个文件名,如果不使用-o指定文件名,gcc会将预处理后的代码输出到屏幕上,只有指定文件名才能保存为文件!

 

代码的预处理会将头文件展开,替换宏,删除注释并执行条件编译等操作,这样才能生成一个纯C语言的代码文本方便后面继续转换!

使用vim打开后里面都是预处理后的代码

这里我们使用-E选项是让编译器执行完预处理就停下! 


编译指令-S

指令:

gcc -S [.c文件/.i预处理文件] //默认生成的文件与编译前的文件名相同但是后缀为.s
gcc -S [.c文件/.i预处理文件] -o [文件名].s //指定生成汇编代码的文件名

这里如果我们不使用-o选项编译器会生成与被编译文件名一样的文件但后缀为.s,且这里既可以对.c代码文件编译,也可以对预处理文件.i进行编译,只不过对.c文件进行编译会先执行预处理然后再执行编译,执行完编译就停下,而预处理文件则是直接进行编译然后停止!

 

编译会对预处理代码进行语法词法并和语义分析,并进行符号汇总等,然后转换为汇编代码。

vim打开编译的文件里面是汇编代码和一些符号标记

汇编指令-c

指令:

gcc -c [.c文件/.i预处理文件/.s编译文件] //默认生成与被执行文件的文件名相同后缀为.o的二进制文件
gcc -c [.c文件/.i预处理文件/.s编译文件] -o [文件名].o

这里如果我们不使用-o选项编译器会生成与被编译文件名一样的文件但后缀为.o,且这里既可以对.c代码文件,.i代码文件和.s汇编代码文件进行汇编,只不过对.c文件进行编译会先执行预处理然和编译,然后执行汇编后就停下;.i文件会先执行编译再执行汇编就停下,.s文件则直接进行汇编然后停下!

 

汇编是将汇编代码转换为二进制汇编文件且生成符号表,这里的二进制文件通过file指令查看是elf格式,通过vim打开会显示一片乱码!

 我们如果想查看这个文件,需要通过指令:

readelf -a [二进制文件.o]

 有需要的小伙伴如果缺失这个功能可以通过yum下载!指令:

yum -y install readelf

链接指令gcc

指令:

gcc [.c/.i/.s/.o文件] //默认生成a.out可执行程序(可使用-o自定义名称)

链接是形成程序的最后一步,如果前面缺少一步就会先执行没有进行的步骤!

链接会进行合并段表,将符号表进行合并和重定位等;然后会将程序与运行所需要的各种函数和库函数链接起来(编译器默认动态链接),生成可执行程序的格式是elf,也可以通过readelf指令查看!


命令巧记口诀

指令 ESc (键盘上的退出键),文件后缀 iso (镜像文件格式)


 链接库


我们都知道,每种语言都有属于自己的库,比如C语言的stdio标准库等,C++有iostream库,当程序在在运行中调用库函数时就会通过地址去库中找这个函数进行调用!在Linux系统中,标准库在 /usr/include/ 目录下,在这个目录下,是Linux系统的各种C语言动态库,除了动态库的概念外,还有静态库的概念,我们慢慢介绍!

Linux系统下的各种库

库文件格式为:lib文件名.a/so,识别时去掉lib和后缀就是文件名!

动态库的文件格式为:lib文件名.so

静态库的文件格式为:lib文件名.a

 

在Linux系统中,指令也是可执行程序都是C语言写的依赖库!


动态库-动态链接

动态库又称共享库,动态库是动态链接的库,如果程序中有该库的函数和引用则会在调用位置留下一个链接,程序运行调用该函数时就会通过这个链接找到对应的库函数并执行!这样动态库只需要存一份代码就可以实现多个程序的调用!

 

链接就是将代码中使用的库函数与对应的库链接(将调用的库函数的文件地址拷贝到文件中)。

动态库一旦被删掉,那么所有依赖该库的程序就无法执行了;动态链接只是拷贝库的地址,执行时需要跳转到库中执行。

 

在Linux系统下gcc和g++链接是默认动态链接库的,如果我们想查看文件的链接方式,指令为:

ldd [文件/程序]  //查看程序链接库方式
打开后会显示各种链接状态且可以看到动态链接的文件后缀都是.so
通过file指令还可以查看可执行程序的链接情况!

 这也说明Linux是默认动态链接的!动态链接的好处在于编译出来的程序体积小,但是跨平台能力差!


静态库-静态链接

静态库采用静态链接的方式,静态链接与动态链接不同之处在于,动态库在调用库函数时根据地址去库中寻找并调用,而静态链接则是将调用的库函数拷贝到自己的代码文件中,相当于本地存储,后续直接执行本地代码文件,不依赖任何动态库!

如果需要静态库编译代码,指令是:

gcc [-选项] [.c文件] -static

可以在预处理-编译-汇编-链接这四个阶段选择静态链接,因为链接是最后一步!

Linux的静态库需要手动安装,指令是:

yum -y install glibc-static //下载静态库

 ldd指令显示文件没有链接任何库!file指令显示可执行程序是静态链接!

 而且静态库链接因为将库代码拷贝到了本地文件,其文件体积将会变得非常大!所以Linux中默认动态链接的方式!


动静态库对比

区别动态库静态库
库函数调用方式通过链接去库中调用在本地代码中调用
跨平台性与依赖性需要依赖库运行,跨平台性差不需要依赖库,跨平台性良好
空间占用空间占用小空间占用大
加载速度需要根据链接去找库函数然后执行直接执行本地库函数代码
优点

可以实现不同进程间的资源共享,对于函数的升级只需要替换动态库文件,不需要重新编译程序,可以控制是否加载动态库,不调用函数时就不加载

所需函数直接拷贝至程序中,运行速度快程序运行无需依赖库,便于移植和跨平台 

缺点

需要调用函数,加载速度较慢,程序运行需要依赖动态库

对于函数的升级,需要重新进行编译同一份代码可能出现重复拷贝的情况,浪费空间


其他指令


声明与定义分离的编译指令

gcc [-选项] [头文件.h] [实现代码.c] [主函数.c]

声明与定义分离,只需要将程序的所有相关文件列入gcc中,然后正常编译即可!


C99标准编译指令

gcc [-选项] [.c文件] -std=c99 //以C99标准编译代码

当我们想要C99标准语法时可以使用该指令编译!


gcc和g++的联系与区别


gcc和g++都是GNU(一个组织)的编译器。

 
1、对于.c后缀的文件,gcc把它当做是C程序;g++当做是C++程序;

2、对于.cpp后缀的文件,gcc和g++都会当做c++程序。

3、编译阶段,g++会调用gcc;

4、连接阶段,通常会用g++来完成,这是因为gcc命令不能自动和c++程序使用的库连接。


 最后

Linux编译器gcc/g++的介绍到这里就结束了,相信学完的老铁肯定想动手写两个程序吧?gcc和g++如此强大的功能来自于GNU组织的开发,让我们可以在Linux上看到代码的底层知识!本节也介绍了动态库和静态库的区别和优缺点,相信大家以后能对库进行合理利用,开发出好的作品!

本次Linux编译器gcc/g++的基本知识就介绍到这里啦,希望能够尽可能帮助到大家。

如果文章中有瑕疵,还请各位大佬细心点评和留言,我将立即修补错误,谢谢!

 🌟其他文章阅读推荐🌟

Linux基础指令-CSDN博客

Linux权限的基本知识-CSDN博客

Linux编辑器vim-CSDN博客

🌹欢迎读者多多浏览多多支持!🌹​​​​​​​

相关文章:

Linux 编译器 gcc/g++

本文已收录至《Linux知识与编程》专栏! 作者:ARMCSKGT 演示环境:CentOS 7 目录 前言 正文 gcc/g常用命令 自定义可执行程序名命令-o 预处理指令-E 编译指令-S 汇编指令-c 链接指令gcc 命令巧记口诀 链接库 动态库-动态链接 静态库…...

2.Java基础【Java面试第三季】

2.Java基础【Java面试第三季】前言推荐2.Java基础01_字符串常量Java内部加载-上58同城的java字符串常量池面试code讲解intern()方法---源码解释02_字符串常量Java内部加载-下whyOpenJDK8底层源码说明递推步骤总结考查点03_闲聊力扣算法第一题字节跳动两数求和题目说明面试题解法…...

Java高级-多线程

本篇讲解java多线程 基本概念: 程序、进程、线程 **程序(program)**是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。 **进程(process)**是程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程…...

mysql高级(事务、存储引擎、索引、锁、sql优化、MVCC)

文章目录1.事务1.1 四大特性ACID1.2 并发事务2.存储引擎2.1 InnoDB2.2 MyISAM2.3 Memory2.4 存储引擎特点2.5 存储引擎的选择3.性能分析3.1 查看执行频次3.2 慢查询日志3.3 profile3.4 explain4.索引4.1 索引结构B-TreeBTreeHash面试题4.2 索引分类思考题4.3 语法4.4 使用规则最…...

Java后端开发功能模块思路

文章目录前言一、查找接口及参数信息1.1 找访问路径1.2 参数及返回结果信息1.3 编写功能模块函数二、代码设计思路三、总结前言 对于正在学习Java后端开发的同学来说,对于Java后端功能模块的开发过程及思路要有一个整体清晰的流程。才能保证在开发过程中更加的顺畅…...

CAPL(vTESTStudio) - DoIP - TCP发送_05

TCP发送 参数定义 版本号:02 FD or 01 FE or 其他任意值数据类型:00 05 or 00 06 or 80 01 or其他任意值数据长度:想要发送的任意长度...

使用IntelliJ IDEA搭建datax-web开发环境

记录:372场景:使用IntelliJ IDEA搭建datax-web开发环境,以及datax-web基本使用。版本:JDK 1.8Python 2.7.5datax-web开源地址:https://github.com/WeiYe-Jing/datax-web1.配置Maven环境1.1安装目录目录:D:\…...

[SSD固态硬盘技术 14] GC垃圾回收太重要了

今天介绍臭名昭著的垃圾收集 过程(或“GC”),maybe 这是对JAVA 工程师而言。当遇到GC导致速度降低时候, 他们真的想跳脚。 我想到我的小孩打疫苗,哭的哇哇叫, 在他的眼里疫苗应该也是讨厌的吧, 但事实真的如此吗? 但首先,让我们考虑一下如果根本没有 GC,闪存系统会发…...

lamada表达式、stream、collect整理

lamada表达式格式 格式:( parameter-list ) -> { expression-or-statements } 实例:简化匿名内部类的写法 原本写法: public class LamadaTest { public static void main(String[] args) { new Thread(new Runnable() { …...

Nacos 入门微服务项目实战

Nacos 核心源码精讲 - IT贱男 - 掘金小册全方位源码精讲,深度剖析 Nacos 注册中心和配置中心的核心思想。「Nacos 核心源码精讲」由IT贱男撰写,375人购买https://s.juejin.cn/ds/BuC3Vs9/ Hi,大家好,欢迎大家来学习《Nacos 核心源…...

【c++】类和对象:让你明白“面向一个对象有多重要”:构造函数,析构函数,拷贝构造函数的深入学习

文章目录 什么是面向对象?一:类是什么? 1.类的访问限定符 2.封装 3.类的实例化 4.this指针二:类的6个默认成员函数 1.构造函数 2.析构函数 3.拷贝构造函数什么是面向对象? c语言是面向…...

职场IT老手教你3步教你玩转可视化大屏设计,让领导眼前一亮!

我是制造企业的IT中心的研发人员,平常工作就是配合业务部门出出报表,选型一些商业软件,并在内部负责实施运维。最近领导出去参观了一些数字化转型比较领先的工厂和制造企业,回来就甩给我几张图,问能不能我们也做几个这…...

【光伏功率预测】基于EMD-PCA-LSTM的光伏功率预测模型(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

大数据Kylin(二):Kylin安装使用

文章目录 Kylin安装使用 一、Kylin安装要求 二、Kylin安装 1、Kylin安装前环境准备...

我们的微服务中为什么需要网关?

说起 Spring Cloud Gateway 的使用场景,我相信很多小伙伴都能够脱口而出认证二字,确实,在网关中完成认证操作,确实是 Gateway 的重要使用场景之一,然而并不是唯一的使用场景。在微服务中使用网关的好处可太多了&#x…...

互联网医院源码 线上问诊 智慧医院源码 C#源码

互联网医院平台源码 智慧医院管理系统源码 开发环境:ASP.NET C# VS2019 SQL2008 依托于实体医院利用互联网技术对接院内业务信息系统,向患者提供基于线上问诊、预约挂号、缴费结算、医患互动、诊后随访、健康科普和复诊等全面的医疗健康互联网服务。…...

基于昇腾计算语言AscendCL开发AI推理应用

01 初始AscendCL AscendCL(Ascend Computing Language,昇腾计算语言)是昇腾计算开放编程框架,是对底层昇腾计算服务接口的封装,它提供运行时资源(例如设备、内存等)管理、模型加载与执行、算子…...

JS document.write()换行

换行效果&#xff1a; 通过传递多个参数&#xff0c;即可实现换行效果&#xff1a; document.write("<br>",ar) 效果&#xff1a; 示例源码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&quo…...

Java高级-集合-Collection部分

本篇讲解java集合 集合 集合框架的概述 集合、数组都是对多个数据进行存储操作的结构&#xff0c;简称Java容器。 说明&#xff1a;此时的存储&#xff0c;主要指的是内存层面的存储&#xff0c;不涉及到持久化的存储&#xff08;.txt,.jpg,.avi&#xff0c;数据库中&#xf…...

Android性能优化:getResources()与Binder交火导致的界面卡顿优化

欢迎&#xff1a;https://juejin.cn/post/7198430801851531324/ 欢迎&#xff1a;https://nasdaqgodzilla.github.io/2023/02/10/Android%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%EF%BC%9AgetResources-%E4%B8%8EBinder%E4%BA%A4%E7%81%AB%E5%AF%BC%E8%87%B4%E7%9A%84%E7%95%8C%E…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

规则与人性的天平——由高考迟到事件引发的思考

当那位身着校服的考生在考场关闭1分钟后狂奔而至&#xff0c;他涨红的脸上写满绝望。铁门内秒针划过的弧度&#xff0c;成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定"&#xff0c;构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...