Linux中gcc/g++的基本使用

news2024/12/25 0:15:09

目录

  • gcc/g++的使用
  • gcc/g++是如何生成可执行文件的
    • 预处理
    • 编译
    • 汇编
    • 链接
    • .o文件是如何与库链接的?
  • debug版本和release版本

gcc/g++的使用

在windows中,我们在VS中编写好了代码之后就可以直接在VS中对源码进行编译等操作后运行
而在Linux下,我们可以使用gcc/g++编译器

gcc只能处理C语言代码
g++可以处理C++代码,也兼容C语言

对于一些指令和选项,在gcc和g++中是一样的,所以本文只介绍gcc的用法

假如现在,我们已经写好了一个C语言代码mycode.c,那么怎么将这个代码进行一些列处理,最后去运行它呢?

下面一条指令就可以:

gcc mycode.c

这条指令会默认让其可执行文件命名为a.out
如果想要自定义可执行程序,可以使用选项-o

gcc mycode.c -o mycode  

这样,生成的可执行文件就叫做mycode了,并且这个写法是最推荐的写法

gcc -o mycode mycode.c这样的写法也可,记住-o选项后面永远跟着重命名的可执行程序名

接下来想要执行这个文件,执行指令:./mycode



gcc/g++是如何生成可执行文件的

从源码开始,经过预处理,编译,汇编,链接四个步骤后,才能生成可执行程序
在gcc中,也有相应的选项去对文件进行只预处理,只编译,只汇编,只链接

下面介绍一下每个步骤的主要功能以及在gcc中相应操作
我们使用的源码很简单:

 #include<stdio.h>
 #define N 10
//主函数
int main()
{
  for(int i = 0;i<N;i++)
  {
     printf("%d ",i);                                                                                                            
  }
  return 0;
}

预处理

在预处理阶段,主要功能包括:展开头文件,宏替换,去注释,条件编译
gcc中的选项为-E
-E选项告诉gcc,从现在开始进行程序的翻译,将预处理做完就停下来,不再往后走
我们常将预处理后的文件命名为以.i后缀结尾的文件

gcc -E mycode.c -o mycode.i

其实,预处理后的文件还是c语言的代码,只是将头文件展开,宏替换,去注释,条件编译

我们可以用vim查看mycode.i文件
我们可以发现,mycode.i的代码有800多行,原因就是将头文件stdio.h进行了展开
查看最后面,我们可以看见自己写的代码,可以发现我们写的注释消失了,并且宏N也被替换成了10,说明也发生了去注释和宏替换
在这里插入图片描述

因为文中的代码没有涉及条件编译,所以这里显现不出条件编译的结果

在这一阶段,我们还可以使用-D选项进行添加宏

gcc -E mycode.c -o mycode.i -D DEBUG #添加宏DEBUG

编译

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

gcc中,选项- S,告诉gcc,从现在开始进行程序的翻译,将编译工作做完就停下来,不要往后走了
我们通常将编译后的汇编语言文件命名为.s后缀的文件

下面将mycode.i进行编译:

gcc -S mycode.i -o mycode.s

#从mycode.c还是也可以
gcc -S mycode.c -o mycode.s

进入mycode.s查看,可以看出里面是汇编代码
在这里插入图片描述

汇编

汇编阶段就是把汇编代码转化成机器可以识别的二进制代码

gcc中,选项-c,告诉gcc,从现在开始进行程序的翻译,将汇编工作做完就停下来,不要往后走了
我们通常将编译后的二进制机器码文件命名为.o后缀的文件

.o文件也叫做可重定位目标二进制文件,简称目标文件,即windows下的.obj文件,虽然是二进制,但还不可以独立执行,需要链接

gcc -c mycode.s -o mycode.o

用vim查看mycode.o文件,发现全是乱码
在这里插入图片描述
其实这是正确的现象,因为汇编之后文件中全是二进制的代码,而我们用的vim是文本编辑器,它将文件以文本的形式打开,所以会将二进制代码识别为对应的字符或符号

所以许多二进制转化为字符或符号后,它们就会组成一篇乱码,正如图片所示

链接

这个步骤,是将可重定位二进制文件与库进行连接成可执行文件

gcc中,连接没有选项

gcc mycode.o -o mycode

此时,预处理,编译,汇编,链接就都完成了,成功生成了可执行文件

readelf -S指令可以读取可执行文件对应二进制构成
在这里插入图片描述

最后,总结一下:
在这里插入图片描述



前面讲链接的时候提到了库。什么是库呢?

在C程序中,我们时常使用一些库函数,实际上,我们使用库函数只是在调用函数,这些库函数的声明在头文件中,而库函数的实现就是在库中

Linux中,存放库的目录为/usr/lib64
C语言的标准库:/usr/lib64/libc.so

其实库的本质就是一个文件
在Linux中,动态库以.so为结尾,静态库以.ac结尾
在Windows中,动态库以.dll为结尾,静态库以.lib结尾

在Linux中,库是有自己的命名规则的,拿动态库为例:libname.so.xxx
而在Linux中,默认只有动态库,静态库是没有安装的

安装静态库:

yum install -y glibc-static
yum install -y libstdc++-static

为什么在下载完VS IDE后就可以写程序了呢?
原因是,编译型语言,安装开发包,必定下载对应的头文件和库文件,所以可以直接进行编写代码

而库就是把源文件,经过一定的翻译,然后打包成库,这样就可以提供一个库文件,不用提供太多的源文件,同时也达到了隐藏源文件的目的

头文件提供方法的声明,库文件提供方法的实现+自己的代码 = 自己的程序

库的最主要功能就是避免重复工作,将已经实现的功能进行打包,供别人调用使用

.o文件是如何与库链接的?

有2中链接方式:1.动态链接 2.静态链接

动态链接:
动态链接就是所有的代码都共用一个动态库,所以动态库也叫做共享库
动态链接将动态库所处的位置拷贝到可执行文件中,在运行程序时到调用库函数的时候,会跳转到库中执行,执行完毕后,再跳会代码的调用处,继续向下执行

在这里插入图片描述

动态库不能缺失,一旦动态库缺失,影响的不止是一个程序,会导致许多程序无法正常运行

在Linux中,更不能随意删除动态库,因为Linux和Unix本身就是用C/C++编写的,其中许多的命令都会调用库函数,如果删除了动态库,不仅我们自己的代码会无法运行,就连内置的命令都无法运行,此时的Linux就可以算是废了

用指令ldd可以查看可执行程序依赖的动态库
在这里插入图片描述

静态链接:
在编译器使用静态库进行静态链接时,会将自己的方法拷贝到目标程序中,使程序不再依赖静态库

在这里插入图片描述
总结一下动态链接/库 和 静态链接/库

  • 不论是动态库还是静态库,本质上就是2个文件,里面包含了各种的源码
  • 静态链接:链接时,把库中代码拷贝自己的可执行程序里
  • 动态链接:在可执行程序中不拷贝实现,只是把实现所在的位置拷贝到可执行文件中
  • 静态链接后,程序不再依赖静态库
  • 动态链接后,程序仍依赖动态库

Linux中,编译行程可执行代码,默认采用动态链接
通过ldd指令可以看出,我们前面生成的可执行程序mycode依赖的是动态库
在这里插入图片描述
在Linux中,如果要使用静态链接,要手动添加-static,并且同时系统中要有静态库,因为静态库不是系统默认提供的
下面我们将mycode.o进行静态链接

gcc mycode.o -o mycode_static -static

用ldd查看,可以看出它使用静态链接
在这里插入图片描述

同时,应为与动态链接相比,静态链接是将静态库中的方法实现拷贝到了可执行文件中,所以采用静态链接的可执行文件的大小一定大于采用动态链接的可执行文件大小
在这里插入图片描述
因为采取静态链接会使可执行文件大小大很多,对于传输和下载这个文件会消耗许多时间和网络,所以动态链接并不常用

用file指令可以查看一个可执行程序是动态链接的还是静态链接的
在这里插入图片描述

有几点需要注意:

  • 如果没有静态库,还添加 -static,是不行的
  • 如果没有如果没有动态库,只有动态库,并且gcc能找到,不添加-static是可以的,因为gcc默认优先动态链接,没有动态库,就使用静态链接,而添加-static本质上是改变优先级
  • 一个可执行程序不一定全部是动态链接或静态链接,也可以是混合的,因为我们的程序可能依赖各种的库,有的库提供了动态库,可能有的库没有提供,所以可以混合使用。如果加了-static,则是让所有链接都变为动态链接,如果库不存在,则会报错

动态链接和静态链接比较:
动态链接的优点:动态库是共享的,可以有效地节省资源(硬盘空间,内存空间,网络空间等)
动态链接的缺点:动态库一旦缺失,程序将无法正常运行

静态链接的优点:不依赖库,一旦形成可执行文件,可以独立运行,可以在同平台环境下随便运行
静态链接的缺点:体积大,占空间


debug版本和release版本

gcc默认以release模式生成可执行文件
要以debug版本生成可执行文件:

gcc mycode.c -o mycode_debug -g 

mycode_debug文件占的空间会比release版本大,因为debug可以被追踪、调试,生成可执行文件时,向里面添加了debug信息

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

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

相关文章

C++_vector操作使用

文章目录 &#x1f680;1.1 vector介绍&#x1f680;1.2 vector的初始化&#x1f680;1.3 vector的常用内置函数&#x1f680;1.4 vector的遍历 &#x1f680;1.1 vector介绍 vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元…

领域知识 | 智能驾驶安全领域部分常见概论

Hi&#xff0c;早。 最近想买个新能源车&#xff0c;这个车吧相比于之前的内燃车&#xff0c;新能源车与外界的交互多了很多。比如娱乐的第三方应用&#xff0c;OTA升级等应用。 交互带来的便利越多&#xff0c;暴露的风险自然也就越大&#xff0c;相比于手机等消费者终端设备…

tomcat三级指导

版本 ./catalina.sh linux version.bat win 1.确认是否使用了tomcat管理后台 我们先找到配置文件&#xff1a;tomcat主目录下/conf/server.xml 可以查看到连接端口&#xff0c;默认为8080 然后查看manager-gui管理页面配置文件&#xff0c;是否设置了用户登录 配置文件…

【C语言回顾】动态内存管理

前言1. 动态内存管理初步概述2. malloc3. calloc4. realloc5. free6. 常见的动态内存错误7. 柔性数组8. 程序内存区域划分结语 #include<GUIQU.h> int main { 上期回顾: 【C语言回顾】联合和枚举 个人主页&#xff1a;C_GUIQU 专栏&#xff1a;【C语言学习】 return 一键…

人工智能再现大脑细胞导航的活动模式

人工智能再现大脑细胞导航的活动模式 李升伟 编译 深度学习算法可自发模拟特殊神经元的活动&#xff0c;这种神经元活动可以告诉我们在空间的位置。 大鼠使用被称为网格细胞的大脑细胞帮助它们导航&#xff0c;人工智能程序已经可以再现这种能力。 科学家已经使用人工智能来再…

网络初识 一

一、网络发展史 1.1 独立模式 最开始的网络,计算机之间是相互独立的. 比如,三个计算机分别存着各自的数据,A正在获取第一台计算机的数据,等要获取第二台计算机的数据时要移动到第二台计算机那里,B想要获取第一台计算机的数据,就要等A使用完. 1.2 网络互连 随着时代的发展,…

Codigger编码场景介绍(二):驾驶舱场景(Cockpit)

Codigger&#xff0c;一个专为开发人员设计的工具&#xff0c;致力于为不同的开发场景提供最佳的切换体验。Codigger囊括了多种场景&#xff0c;如传统场景、调试场景、设计器场景、驾驶舱场景以及纯净场景等。在上一篇文章中&#xff0c;我们介绍了传统场景模式&#xff0c;今…

Linux 应用入门(一)

1. 交叉编译 概念&#xff1a;在当前编译平台下&#xff0c;编译出来的程序能运行在体系结构不同的另一种目标平台上&#xff0c;但是编译平台本身却不能运行该程序。 为什么需要交叉编译&#xff1f; 速度&#xff1a;目标平台得运行速度比主机往往慢得多&#xff0c;因为许多…

Linux程序开发(十一):进程与进程间通信设计之趣味猫咪抓老鼠游戏

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

在未来你将何去何从?

在数字化的浪潮中&#xff0c;信息技术行业无疑是推动全球经济和社会发展的重要动力。随着科技的不断迭代与进步&#xff0c;云计算、大数据、人工智能&#xff08;AI&#xff09;、物联网&#xff08;IoT&#xff09;、5G通信和区块链等技术已经深入到我们生活的每一个角落&am…

Python调用科大讯飞在线语音合成API --内附完整项目

一&#xff0c;注册讯飞账号&#xff0c;并实名制。 讯飞开放平台-以语音交互为核心的人工智能开放平台 (xfyun.cn) 二、找到音频合成&#xff0c;按页面提示申请免费试用。 在线语音合成_免费试用-讯飞开放平台 (xfyun.cn) 三、申请免费使用后&#xff0c;找到API信息如下…

数据仓库ETL

小白的数据仓库学习笔记 2024/5/20 18:25 文章目录 ETLdim打开创建项目&#xff08;选这个&#xff0c;这个是做etl的&#xff09;建立元数据的连接同样的&#xff0c;建立与数据仓库的连接新建ssis包序列容器全量etl增量etl建立sql任务双击打开&#xff0c;设置连接、内容 双击…

共享单车(八):数据库

实现后台数据库访问模块的框架&#xff0c;能够实现验证请求并响应&#xff08;支持数据库操作&#xff09;。 数据库设计 class SqlTabel //负责数据库表的创建 { public:SqlTabel(std::shared_ptr<MysqlConnection> sqlconn) :sqlconn_(sqlconn) {}bool CreateUserI…

BeautifulSoup4通过lxml使用Xpath,以及获取(定位)元素和其文本或者属性

环境&#xff1a;win10&#xff0c;python3.8.10 首先需要安装&#xff1a;beautifulsoup4&#xff0c;lxml 使用命令&#xff1a; pip38 install beautifulsoup4 pip38 install lxml 安装完毕后查看一下&#xff1a; 写代码&#xff1a; from bs4 import BeautifulSoup …

5.24机器人基础-入门1

参考书籍&#xff1a;《机器人学导论》John.J.Craig 机器人方面的学习和线性代数、矩阵论部分的学习密切相关&#xff0c;建议先学习线性代数会更好理解此部分内容。虽然学了线代但是能忘的都忘得差不多的我要泪目了。本文主要介绍基础的运动学和动力学区别&#xff0c;正向运…

RocketMQ 架构原理

注册中心 注册中心使用得nameserver, nameserver不会进行频繁的读写&#xff0c;所以整体的性能开销小&#xff0c;稳定性也高。 注册中心没隔10s会扫描一次所有的broker&#xff0c;如果2min没有发送心跳过来&#xff0c;就人为挂了&#xff0c;断开连接。此时会更新topic与队…

IEN在Web3.0中的性能与安全优势

随着Web3.0的快速发展&#xff0c;优化网络基础设施变得至关重要。智能生态网络&#xff08;Intelligent Ecological Network, IEN&#xff09;作为新一代网络架构&#xff0c;在提升性能与增强安全方面展现出巨大潜力。本文将深入探讨IEN在Web3.0中的技术优势&#xff0c;并展…

Linux安装Docker教程(实测可用)

前言 Docker是一个开源的应用容器引擎&#xff0c;它允许开发者将应用程序及其依赖打包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上。以下是对Docker的具体介绍&#xff1a; 技术起源&#xff1a;容器技术起源于程序员对于环境搭建与应用部署效…

data studio连接到虚拟机上的openGauss

参考&#xff1a;使用DataStudio连接本地虚拟机中的opengauss数据库_big data_白日梦想家_胖七七-华为云开发者联盟 本实验虚拟机安装的是CentOS7 数据库版本是&#xff1a;openGauss-5.0.2-CentOS-64bit-all.tar.gz 1.配置pg_hba.conf 首先使用su - omm登录到omm用户&…