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

深入解析 C 语言中含数组和指针的构造体与共同体内存计算

        在 C 语言中,构造体(struct)和共同体(union)允许我们将多种数据类型组合到一起。除了常见的基本数据类型之外,经常还会在它们中嵌入数组和指针。由于数组的内存是连续分配的,而指针的大小与平台相关(32 位一般为 4 字节,64 位一般为 8 字节),计算内存大小时就需要特别注意内存对齐填充的影响。本文将通过具体示例说明如何计算包含数组和指针的构造体和共同体的内存大小。

 一、构造体(Struct)中包含数组和指针

1.1基本原理

  • 数组:数组内存占用空间为“数组元素个数×单个元素大小”,且所有元素是连续排列。
  • 指针:指针只存储一个地址,其大小固定(取决编译平台,与指向数据无关)。
  • 内存对齐与填充:编译器为了提高内存访问效率,会按照每个成员的对齐要求进行排列。如果某个成员的起始地址不满足对齐要求,编译器会在前面插入填充字节。同时整个结构体的大小也会被调整为结构体中最大对齐要求的整倍数。

1.2示例: 构造体包含数组和指针

        假设在 64 位系统下(指针大小为 8 字节,int 为 4 字节,char 为 1 字节),如下构造体的定义为例:

struct Example {char a;        // 1 字节int b;         // 4 字节,要求 4 字节对齐char arr[3];   // 数组,占 3 字节int *ptr;      // 指针,占 8 字节(64 位系统)
};

内存布局分析

1.成员 a(char):

  • 从偏移 0 开始,占 1 字节。

2.成员 b(int):

  • 由于 int 要求 4 字节对齐,而 a 只占 1 字节,所以在 a 后面需要 3 字节填充,使得 b 的起始地址为偏移 4。
  • b 占 4 字节,从偏移 4 到 7。

3.成员 arr[3](数组):

  • 紧接在 b 后面,从偏移 8 开始。
  • 数组大小为 3 字节,覆盖偏移 8、9、10。

4.成员 ptr(指针):

  • 指针要求 8 字节对齐,而当前下一个可用偏移为 11,不满足 8 字节对齐(因为 11 不是 8 的倍数)。
  • 编译器需要在 arr 后插入 5 字节填充,使得 ptr 从偏移 16 开始。
  • ptr 占 8 字节,从偏移 16 到 23。

5.整体大小调整:

  • 当前各部分占用总字节数为 24 字节(0~23),而最大对齐要求为 8 字节,24 已经是 8 的倍数,因此最终结构体大小为 24 字节

1.3 嵌套构造体中包含数组和指针

        假设在 64 位系统下(指针大小为 8 字节,int 为 4 字节,char 为 1 字节),如下构造体的定义为例:

struct Example {char a;        // 1 字节int b;         // 4 字节,要求 4 字节对齐char arr[3];   // 数组,占 3 字节int *ptr;      // 指针,占 8 字节(64 位系统)
};
内存布局分析

1.成员 a(char):

  • 从偏移 0 开始,占 1 字节。

2.成员 b(int):

  • 由于 int 要求 4 字节对齐,而 a 只占 1 字节,所以在 a 后面需要 3 字节填充,使得 b 的起始地址为偏移 4。
  • b 占 4 字节,从偏移 4 到 7。

3.成员 arr[3](数组):

  • 紧接在 b 后面,从偏移 8 开始。
  • 数组大小为 3 字节,覆盖偏移 8、9、10。

4.成员 ptr(指针):

  • 指针要求 8 字节对齐,而当前下一个可用偏移为 11,不满足 8 字节对齐(因为 11 不是 8 的倍数)。
  • 编译器需要在 arr 后插入 5 字节填充,使得 ptr 从偏移 16 开始。
  • ptr 占 8 字节,从偏移 16 到 23。

5.整体大小调整:

  • 当前各部分占用总字节数为 24 字节(0~23),而最大对齐要求为 8 字节,24 已经是 8 的倍数,因此最终结构体大小为 24 字节

二、共同体(union)中包含数组和指针 

2.1 基本原理

        在共同体中,所有成员共享同一块内存,其大小由最大成员的大小决定,同时也需要满足该成员的对齐要求。即使共同体中包含数组和指针,原则也是一致的。

2.2 示例:共同体中包含数组和指针

union Union {int arr[4];    // 数组:4 个 int,每个 4 字节,总共 16 字节double *dptr;  // 指针,8 字节(64 位系统)char c[10];    // 数组:10 个 char,总 10 字节
};
内存大小计算
  • arr[4] 占 4 × 4 = 16 字节
  • dptr 占 8 字节
  • c[10] 占 10 字节

取最大值: 最大成员为 arr[4],大小为 16 字节。
同时需要考虑最大对齐要求,假设 int 要求 4 字节,而指针要求 8 字节;由于最大成员(数组)的元素对齐为 4 字节,但联合体的整体对齐要求通常取决于所有成员中最大的(这里可能由指针决定为 8 字节),不过最终分配空间依旧是 16 字节(且该空间会按 8 字节对齐)。因此,该共同体的总大小为 16 字节

三、总结与注意事项

1.构造体(struct):

  • 内存分布为成员按照声明顺序排列。
  • 数组成员按照数组中所有元素总大小分配。
  • 指针成员只占指针本身大小,不考虑所指数据。
  • 必须考虑每个成员的对齐要求,必要时插入填充字节,整体大小也需调整为最大对齐要求的整数倍。
  • 嵌套构造体时,先计算内部结构体的大小,再按照外部成员的排列顺序计算整体大小。

2.共同体(union):

  • 所有成员共享同一块内存,大小取决于最大的成员(同时满足对齐要求)。
  • 数组和指针的计算方法依然适用,但只取最大值即可。

相关文章:

深入解析 C 语言中含数组和指针的构造体与共同体内存计算

在 C 语言中,构造体(struct)和共同体(union)允许我们将多种数据类型组合到一起。除了常见的基本数据类型之外,经常还会在它们中嵌入数组和指针。由于数组的内存是连续分配的,而指针的大小与平台…...

【C++模板】:开启泛型编程之门(函数模版,类模板)

📝前言: 在上一篇文章C内存管理中我们介绍了C的内存管理,重点介绍了与C语言的区别,以及new和delete。这篇文章我们将介绍C的利器——模板。 在C编程世界里,模板是一项强大的特性,它为泛型编程奠定了坚实基础…...

HEC-HMS水文建模全解析:气候变化与极端水文、离散化流域单元‌精准刻画地表径流、基流与河道演进过程‌

一、技术革新:数字流域的精密算法革命 在全球气候变化与极端水文事件频发的双重压力下,HEC-HMS模型凭借其‌半分布式建模架构‌与‌多尺度仿真能力‌,已成为现代流域管理的核心工具。该模型通过‌离散化流域单元‌精准刻画地表径流、基流与河…...

具备多种功能的PDF文件处理工具

软件介绍 在日常办公和学习场景中,PDF文件使用极为频繁,而一款功能强大的PDF编辑软件能大幅提升处理效率。 今天要介绍的Adobe Acrobat Pro DC 2024.005.20414,就具备像编辑Word文档一样便捷编辑PDF的能力。 PDF文档在学习和工作中广泛应用…...

【SpringMVC】SpringMVC的启动过程与原理分析:从源码到实战

SpringMVC的启动过程与原理分析:从源码到实战 SpringMVC是Spring框架中用于构建Web应用的核心模块,它基于MVC(Model-View-Controller)设计模式,提供了灵活且强大的Web开发能力。本文将深入分析SpringMVC的启动过程、核…...

转自南京日报:天洑软件创新AI+仿真技术变制造为“智造

以下文章来源:南京日报 进入3月,南京天洑软件有限公司(以下简称天洑软件)董事长张明更加忙碌。“公司强调工业软件在数字经济与先进制造业融合中的关键作用,并已广泛应用在能源、电力和航空等领域。”他说,…...

golang dlv调试工具

golang dlv调试工具 在goland2022.2版本 中调试go程序报错 WARNING: undefined behavior - version of Delve is too old for Go version 1.20.7 (maximum supported version 1.19) 即使你go install了新的dlv也无济于事 分析得出Goland实际使用的是 Goland安装目录下dlv 例…...

LSTM方法实践——基于LSTM的汽车销量时序建模与预测分析

Hi,大家好,我是半亩花海。本实验基于汽车销量时序数据,使用LSTM网络(长短期记忆网络)构建时间序列预测模型。通过数据预处理、模型训练与评估等完整流程,验证LSTM在短期时序预测中的有效性。 目录 一、实验…...

微服务——网关、网关登录校验、OpenFeign传递共享信息、Nacos共享配置以及热更新、动态路由

之前学习了Nacos,用于发现并注册、管理项目里所有的微服务,而OpenFeign简化微服务之间的通信,而为了使得前端可以使用微服务项目里的每一个微服务的接口,就应该将所有微服务的接口管理起来方便前端调用,所以有了网关。…...

【数据结构】二叉搜索树、平衡搜索树、红黑树

二叉搜索树(Binary Search Tree) 二叉搜索树是一种特殊的二叉树,它用来快速搜索某个值,对于每个节点都应该满足以下条件: 若该节点有左子树,那么左子树中所有节点的值都应该小于该节点的值。若该节点有右…...

Spring Boot 解析 LocalDateTime 失败?Uniapp 传输时间变 1970 的原因与解决方案

目录 前言1. 问题分析2. 时间戳(推荐,可尝试)3. 使用 JsonDeserialize & JsonSerialize(中立)4. 前端传 ISO-8601 格式(不推荐,可尝试)5. 用 String(中立&#xff09…...

Xilinx ZYNQ FSBL解读:LoadBootImage()

篇首 最近突发奇想,Xilinx 的集成开发环境已经很好了,很多必要的代码都直接生成了,这给开发者带来了巨大便利的同时,也让人错过了很多代码的精彩,可能有很多人用了很多年了,都还无法清楚的理解其中过程。博…...

mysql中in和exists的区别?

大家好,我是锋哥。今天分享关于【mysql中in和exists的区别?】面试题。希望对大家有帮助; mysql中in和exists的区别? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 MySQL 中,IN 和 EXISTS 都用于进行子查询,但它…...

oracle 数据导出方案

工作中有遇到需要将oracle 数据库表全部导出,还需要去除表数据中的换行符。 方案 shell 设计 封装函数 1 function con_oracle() 用于连接oracle 2 function send_file() 用于发送文件 3 主程序 使用循环将所有表导出并发送到数据服务器 主程序 程序代码 #!…...

Apache Commons Lang3 和 Commons Net 详解

目录 1. Apache Commons Lang3 1.1 什么是 Apache Commons Lang3? 1.2 主要功能 1.3 示例代码 2. Commons Net 2.1 什么是 Commons Net? 2.2 主要功能 2.3 示例代码 3. 总结 3.1 Apache Commons Lang3 3.2 Commons Net 3.3 使用建议 4. 参考…...

从0开始的操作系统手搓教程33:挂载我们的文件系统

目录 代码实现 添加到初始化上 上电看现象 挂载分区可能是一些朋友不理解的——实际上挂载就是将我们的文件系统封装好了的设备(硬盘啊,SD卡啊,U盘啊等等),挂到我们的默认分区路径下。这样我们就能访问到了&#xff…...

【Linux】36.简单的TCP网络程序

文章目录 1. TCP socket API 详解1.1 socket():打开一个网络通讯端口1.2 bind():绑定一个固定的网络地址和端口号1.3 listen():声明sockfd处于监听状态1.4 accept():接受连接1.5 connect():连接服务器 2. 实现一个TCP网络服务器2.1 Log.hpp - "多级日志系统"2.2 Daem…...

时序分析

1、基本概念介绍 1.1、 建立时间 T(su) 建立时间:setup time,它是指有效的边沿信号到来之前,输入端口数据保持稳定的时间。 1.1.1、 建立时间要求: 建立时间要求指的是 想要寄存器如期的工作,在有效时…...

doris:ClickHouse

Doris JDBC Catalog 支持通过标准 JDBC 接口连接 ClickHouse 数据库。本文档介绍如何配置 ClickHouse 数据库连接。 使用须知​ 要连接到 ClickHouse 数据库,您需要 ClickHouse 23.x 或更高版本 (低于此版本未经充分测试)。 ClickHouse 数据库的 JDBC 驱动程序&a…...

NLP常见任务专题介绍(1)-关系抽取(Relation Extraction, RE)任务训练模板

📌 关系抽取(Relation Extraction, RE)任务训练示例 本示例展示如何训练一个关系抽取模型,以识别两个实体之间的关系。 1️⃣ 任务描述 目标:从文本中提取两个实体之间的语义关系,例如 “人物 - 组织”、“药物 - 疾病”、“公司 - 创始人” 等。输入:句子 + 标注的实…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...