【LInux编译器gcc/g++】gcc使用方法和动静态库相关概念

目录

一.前言

二.源代码的翻译环境

三.gcc相关指令

四.动静态库

1.什么是库?

2.库的命名

3.库的链接方式

4.动静态链接的优缺点

5.小结


一.前言

在Windows系统上我们常用VisualStudio来进行C/C++开发,VS并不是一款单一的软件,而是集成开发环境(IDE),其中包含编辑器,编译器,调试器等等,功能很强大。而在LInux当中,我们需要学会使用各项独立的工具才能进行开发,例如用vim编辑代码,用gcc编译代码,用gdb调试代码。

今天我们就来讲讲如何使用gcc来得到我们需要的可执行程序,并介绍编译过程中的动静态库问题。

二.源代码的翻译环境

我们编写的C语言是自然语言,它是供我们人类阅读的,计算机并不懂。所以需要将它翻译成计算机看得懂的二进制语言,而这个翻译过程,就是经常说的编译。

实际上一个或多个源文件变层可执行程序需要经历编译和链接两个阶段,但我们日常所说的编译是把链接阶段也包含在内的,下面我也不再刻意区分这两个阶段。

程序编译的过程包含以下四个阶段

  1. 预处理
  2. 编译
  3. 汇编
  4. 链接

而gcc编译器就是来完成这四项工作的

【注:想要进一步理解程序的翻译过程可参考我以前写的程序的编译(翻译)】

三.gcc相关指令

gcc -E code.c -o code.i

-E表示从现在开始进行程序翻译,等预处理完成就停下来,不要继续往后走了。

-o表示把生成的文件重命名

预处理阶段做了四件事:

  1. 头文件展开
  2. 条件编译
  3. 去注释
  4. 宏替换

得到的code.i文件依然是C语言代码

gcc -S code.i -o code.s

-S表示从现在开始进行程序翻译,等编译完成就停下来,不要继续往后走了。

这里的code.i是否可以换成code.c呢?肯定是可以的,但是没必要,因为这样之前的工作又会被重复做一遍。

这时的code.s文件就是汇编代码了

gcc -c code.s -o code.o

-S表示从现在开始进行程序翻译,等汇编完成就停下来,不要继续往后走了。

完成汇编后,code.o就是一个二进制文件了,但现在它并不能执行,因为还差最后一个链接阶段

gcc code.o mybin

链接并不像前几个阶段一样有专门的选项,因为链接就是翻译的最后一步,通常情况下我们都是直接执行以下指令一步到位,并不会傻傻地把这四个步骤分开做

gcc code.c -o mybin  

细节问题 :

我们在test.c文件中写了这样一段代码

 编译时发现不能通过

这是因为在for循环里定义临时变量c99标准里才支持的,我现在的这款gcc编译器默认是不支持的,要想采用c99标准编译代码,只需在后面加上std=c99即可

gcc  -std=c99  test.c  -o  test.out

四.动静态库

简而言之:.o文件+库=可执行程序

故链接阶段就是将.o文件(可重定位的二进制文件)和库链接起来

那么接下来就有两个问题:什么是库呢?如何链接.o文件和库的呢?

1.什么是库?

下面介绍一个指令

ldd mybin

ldd是用来查看一个可执行程序依赖的第三方库

 

可以看出来mybin依赖三个库,其它两个不管,我们把中间的那个拎出来 

 

我们在LInux系统中找一下,看是否有这个文件

果然有这个文件,而且给普通用户开放的权限还挺高,可读可写可执行。

注意库并不是头文件,预处理阶段include过来的并不是它哟,头文件这个路径下?

 

 头文件放的是函数的声明,库提供方法实现。

头文件+库+我们写的代码=我们的可执行程序

“LInux下一切皆文件“,所以库其实也就是个文件。系统中的头文件和库文件都是文件!所以,所谓的开发环境安装,一定要做什么工作?

安装下载并拷贝头文件和库文件到开发环境中的特定路径下,一定要能被编译器自己找到

在下载VS时,会让你选择安装C++桌面版,游戏开发等环境,说白了就是不同的头文件和库文件嘛

2.库的命名

以libc.so.6这个库为例

库要求以lib开头,so表示这个库是静态库,6是版本号,所以一个库的名字要去掉前缀和后缀,所以这个库的名字就是c,也就是传说中的C标准库。

库分为两类:动态库和静态库,在LInux当中,so表示动态库,a表示静态库。在常规的开发环境中,动态库居多

3.库的链接方式

动态库:是C/C++或其它第三方提供的所有方法的集合,被所有程序以链接的方式关联起来,这种链接方式叫做动态链接

静态库:是C/C++或其它第三方提供的所有方法的集合,被所有程序以拷贝的方式,将需要的代码,拷贝到自己的可执行程序中,这种链接方式叫做静态链接 

库中所有的函数,都有入口地址,所谓的动态链接,其实就是把链接的库中的函数地址拷贝到我们的可执行程序中的特定位置。

4.动静态链接的优缺点

动态链接:优点:形成的可执行程序体积比较小,比较节省资源。

                  缺点:强依赖动态库,动态库没了,所有依赖这个库的程序都无法运行了

静态链接:优点:无视库,可以独立运行

                  缺点:体积太大,浪费资源

LInux系统中的指令,实际上就是一个个可执行程序 

 既然是可执行程序,那我们就能查看它所依赖的库

可以看到,pwd指令也是用C语言写的,它也依赖C标准库。实际上,LInux中的绝大多数指令都是用C/C++写的,如果我们将C标准库删掉,那么这个系统基本也就挂了,因为最基本的指令都无法运行,更别说其它操作了。

接下来我们想看看动静态链接的可执行程序的大小差异,如何做呢?

gcc默认是采用动态链接的方式,去找对应的动态库,所以采用如下指令即可

 

要想静态链接,只需在后面跟上一个-static

但有可能会报出这样的一个错误

这是因为我们的系统里默认是没有安装 C静态库的。我们可以手动安装一下C/C++静态库

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

 最终两个可执行程序都生成了,可以看到它们的体积大小相差了将近100倍,这还是我仅仅在里面写了一个helloworld的情况下。

所以这也能解释为什么编译器默认采用的是动态链接,因为静态链接太浪费空间了。这里的空间不仅仅指磁盘上的空间,还包括内存。你要知道,一个可执行程序要想执行,首先必须是要加载到内存中去的呀,所以使用动态链接加载到内存会更快

5.小结

我们的开发环境,编译器都要为我们做什么?

  1. 下载开发环境(头文件和库文件)
  2. 设置合理的查找路径
  3. 设定好我们形成可执行程序的链接方式

所以编译时出现链接问题,要么是库文件损毁了,要么是路径没或者链接方式没有设定好。

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

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

相关文章

DQN算法概述及基于Pytorch的DQN迷宫实战代码

一. DQN算法概述 1.1 算法定义 Q-Learing是在一个表格中存储动作对应的奖励值,即状态-价值函数Q(s,a),这种算法存在很大的局限性。在现实中很多情况下,强化学习任务所面临的状态空间是连续的,存在无穷多个状态,这种情…

将Apache服务与内网穿透结合,让您的网站可以公网访问

Apache服务安装配置与结合内网穿透实现公网访问 文章目录 Apache服务安装配置与结合内网穿透实现公网访问前言1.Apache服务安装配置1.1 进入官网下载安装包1.2 Apache服务配置 2.安装cpolar内网穿透2.1 注册cpolar账号2.2 下载cpolar客户端 3. 获取远程桌面公网地址3.1 登录cpo…

Android 查看当前手机、APP的ABI架构信息

目录 查看手机 查看APP 查看手机 命令:adb shell "getprop |grep cpu" 命令:adb shell getprop ro.product.cpu.abi 查看APP 在 data/system/packages.xml 文件中找到自己 app 的相关配置信息,这里有明确指出该去哪里加载 so…

C++中菱形继承中的多态在底层是如何实现的。

如果还不了解菱形继承和多态的底层可以看这两篇文章:C中多态的底层实现_Qianxueban的博客-CSDN博客 C的继承以及virtual的底层实现_Qianxueban的博客-CSDN博客 1.只有基类有虚函数 2.派生类也有重写的虚函数

【MySQL数据库原理】MySQL Community 8.0界面工具汉化

尝试以下方法来汉化 MySQL Workbench 8.0 的菜单: 1、使用社区翻译版本:有一些热心的社区成员会将 MySQL Workbench 翻译成不同的语言,包括中文。你可以在一些开源或社区网站上寻找这些翻译版本,并按照他们的说明进行安装。 2、…

博客系统(升级(Spring))(二)获取当前用户信息、对密码进行加密、设置统一数据格式、设置未登录拦截、线程池

博客系统(二) 博客系统获取当前用户的信息对密码进行加密和解密的操作设置统一的数据返回格式设置未登录拦截设置线程池 博客系统 博客系统是干什么的? CSDN就是一个典型的博客系统。而我在这里就是通过模拟实现一个博客系统,这是…

Redis之缓存和数据库双写一致方案讨论解读

目录 什么是缓存双写一致 更新缓存还是删除缓存? 先删除缓存,再更新数据库 场景描述 解决方案:延时双删策略 先更新数据库,再删除缓存 场景描述 解决方案:重试机制引入MQ 为什么要引入MQ 什么是缓存双写一致 只要用缓存…

rsync远程同步

与inodify结合使用,实现实时同步 rsync简介 rsync(Remote Sync,远程同步)是一个开源的快速备份工具,可以在不同主机之间镜像同步整个目录树,;支持增量备份,并保持链接和权限&#…

记录造数据测试接口

一、前言 在java开发中经常需要造数据进行测试接口,这里记录一下常用的通过造数据测试接口的方法。 二、一般的接口传参方式 1、接口的方式最好是使用JSON或者map的方式,这样的好处是传参可以灵活伸缩,返回的结果也最好是JSON或者map的方式…

Redis7--基础篇1(概述,安装、卸载及配置)

1. Redis概述 1.1 什么是Redis Redis:REmote Dictionary Server(远程字典服务器) Remote Dictionary Server(远程字典服务)是完全开源的,使用ANSIC语言编写遵守BSD协议,是一个高性能的Key-Value数据库提供了丰富的数…

MQTT 连接优化指南

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

JVM问题排查

本文详细说明了Java应用运行过程中几种常见的JVM相关问题,并给出了问题排查步骤。 一、堆中OOM 现象:Java线程负载过高,JVM内存几乎占满,甚至抛出java.lang.OutOfMemoryError错误。 思路:通过jmap能查看到对内存中实…

【Apollo 自动驾驶】Win11 中 WSL2 安装配置 Apollo 环境

【Apollo 自动驾驶】Win11 中 WSL2 安装配置 Apollo 环境 【1】Win11 WSL2 安装配置 Nvidia Cuda 【1.1】检查计算机硬件的显卡信息 计算机图标右击 -> 管理 -> 设备管理器 -> 显示适配器; 【1.2】检查对应显卡并安装 Nvidia 显卡驱动 下载对应的 Nv…

第15章_瑞萨MCU零基础入门系列教程之Common I2C总线模块

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id728461040949 配套资料获取:https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总: ht…

vue3+vite项目运行报错[plugin vite:dep-pre-bundle]

报错截图 原因:vue-i18n 插件于9.5更新,打包和引入方式有改变,所以新启动和新部署的项目都会有这个问题。 解决方式: 1.项目全局搜索:vue-i18n/dist/v ue-i18n.cjs.js 然后将搜索到的代码替换为 :vue-i18…

为特征向量数据(1D数组)叠加噪声实现数据增强

为特征向量数据(1D数组)叠加噪声实现数据增强 日期作者版本备注2023.09.11Dog TaoV1.0完成文档的初始版本。 文章目录 为特征向量数据(1D数组)叠加噪声实现数据增强背景介绍叠加噪声的主要方法高斯噪声(Gaussian Nois…

微服务05-Docker基本操作

Docker的定义 1.什么是Docker Docker是一个快速交付应用、运行应用的技术: 可以将程序及其依赖、运行环境一起打包为一个镜像,可以迁移到任意Linux操作系统运行时利用沙箱机制形成隔离容器,各个应用互不干扰启动、移除都可以通过一行命令完…

超详细-Vivado配置Sublime+Sublime实现VHDL语法实时检查

目录 一、前言 二、准备工作 三、Vivado配置Sublime 3.1 Vivado配置Sublime 3.2 环境变量添加 3.3 环境变量验证 3.4 Vivado设置 3.5 配置验证 3.6 解决Vivado配置失败问题 四、Sublime配置 4.1 Sublime安装Package Control 4.2 Sublime安装VHDL插件 4.3 语法检查…

STM32F4X DMA

STM32F4X DMA 什么是DMASTM32F4X DMADMA框图DMA通道DMA仲裁器DMA FIFO DMA传输模式DMA传输方向存储器到存储器存储器到外设外设到存储器 DMA循环模式和普通模式循环模式(Circular)普通模式(Normal) DMA源、目标寄存器增量模式DMA例…

React【组件生命周期 、组件生命周期_挂载、 组件生命周期_更新 、组件生命周期_卸载、表单_受控组件、表单_受控组件处理多个输入】(三)

文章目录 组件生命周期 组件生命周期_挂载 组件生命周期_更新 组件生命周期_卸载 表单_受控组件 表单_受控组件处理多个输入 组件生命周期 每个组件都有自己的生命周期,从“生”到”死“。 在这个过程当中,它会有不同的状态,针对不同的状态…