C语言:自定义类型进阶(结构体、联合体、枚举)
自定义类型(结构体、联合体、枚举)
- 一、结构体
- (一)结构体的内存对齐
- 1、结构体内存对齐规则
- (1)引子
- (2)offsetof 宏函数
- (3)内存对齐原理
- (4)自定义默认对齐数
- 2、为什么要内存对齐
- (1)性能原因
- (2) 平台原因
- (二)结构体实现位段
- 1、位段的定义
- 2、位段的储存
- 3、位段的不可跨平台性
- 4、位段的应用
- 二、枚举
- (一)枚举的定义
- (二)枚举的优点
- 三、联合体
- (一)联合体的储存
- (二)联合体的应用
- 四、结束语
一、结构体
(一)结构体的内存对齐
1、结构体内存对齐规则
(1)引子
结构体占多少内存呢,是不是各个变量的内存之和呢,先用一段代码来验证我们的猜想吧。下面代码中,如果我们猜想正确,那么打印结果就应该是三个变量的字节数之和,答案为6.


(2)offsetof 宏函数
offsetof (type,member) 返回成员变量number距离结构体首地址的偏移量(单位是字节)
我们对结构体S的a, b, c,分别查看他们的偏移量。


根据这个结果,我们可以画出下面的内存图解。

(3)内存对齐原理
1、结构体的第一个成员变量对齐到和结构体首地址偏移量为0的地址处
2、其它成员变量要对齐到对齐数的整数地址处。
对齐数 = 编译器的默认对齐数 和 该结构体成员变量的大小 中的较小值
3、结构体大小为最大对齐数的整数倍。
4、如果结构体嵌套结构体,嵌套的结构体变量要对齐到自己成员变量中最大对齐数整数倍的地址处。结构体大小就是所有成员(包含结构体中的成员)中最大对齐数的整数倍。
求下面代码的输出结果。
struct S1 {double a;char b;int c;
};struct S2 {char a;struct S1 b;double c;
};int main() {printf("%zd", sizeof(S2));return 0;
}
要求结构体S2的大小,我们首先要求结构体S1的大小,分析如下。

接着再求结构体S2的大小

分析结果为32和我们预料的一致。

(4)自定义默认对齐数
使用 #pragma pack(int val)可以设置默认对齐数。
例如:
#pragma pack(1)//将默认对齐数设置为1struct S {char c1;int n;char c2;
}#pragma pack() //重置默认对齐数
2、为什么要内存对齐
所以说不仅步骤麻烦,还消耗了内存,为什么还要内存对齐呢。用空间换时间!
(1)性能原因
为了访问未对齐的数据,处理器需要访问多次,而处理对齐的数据,处理器访问次数减少。
struct S {char a;int b;
};
在32位平台中,我们一次可以访问四个字节。下面我们访问变量 b 并用内存对齐和非内存对齐来对比
内存对齐


非内存对齐
通过非内存对齐,发现我们起码要通过两次才能拿到 int 成员变量。

(2) 平台原因
不是所有平台都能访问任意地址上的任一数据。
(二)结构体实现位段
1、位段的定义
位段中的位指的是二进制位,和结构体类似,有两点不同
1、位段的类型只能是 int 、signed int、unsigned int 或者是char(整形家族),C99中引入了其它类型。
2、位段后面比较加冒号和数字,表示为该变量分配多少个比特位的空间。
如下:
struct S {int a : 2;int b : 6;int c : 4;int c : 4;
};
2、位段的储存
位段也有自己的储存方式,我们分析下面一段代码进行体会
struct S {int a : 3;int b : 4;int c : 5;int d : 4;
};int main() {printf("%d", sizeof(struct S));return 0;
}

注意:
位段在初始化变量时候不可以用scanf,因为&符号是以一个字节为单位,显然如果一个字节里面有多个变量的话,会引发错误。
3、位段的不可跨平台性
1、数据类型解释的不确定性:
有符号与无符号:位段中的int类型成员是否被当作有符号数还是无符号数,在不同的编译器和平台上可能存在差异。
位数限制:位段中成员的最大位数在不同的编译器和平台上可能有所不同。例如,在16位机器上,位段的最大位数可能为16,而在32位机器上可能为32。
2、内存分配方式的不确定性:
分配方向:位段成员在内存中的分配方向(从左到右或从右到左)在C语言标准中并未明确定义,这可能导致在不同的编译器和平台上出现不同的内存布局。
空间利用:当一个结构体包含多个位段成员,且后一个成员无法完全容纳在前一个成员剩余的位中时,是舍弃剩余位还是尝试利用这些位,也是不确定的。
4、位段的应用
网络协议中用来包装IP数据报(就好像外卖一样,需要填写目的地的信息),而位段进行封装就会使得包裹更加便捷。
二、枚举
(一)枚举的定义
我们可以把生活中一些事物所对应的情况一一列举处来,就是枚举。
如下,其中enum就是枚举类型,{}里的内容就是枚举常量。

变量中的枚举常量默认赋初始值为0 1 2 3 … 也可以自定义赋值。自定义赋值时,可以选择性赋值,没有赋值的会序列化自动赋值。
(二)枚举的优点

枚举的优点用以下代码可以充分体现。
enum Option
{EXIT,//0ADD,//1SUB,MUL,DIV
};void menu()
{printf("**********************************\n");printf("****** 1. add 2. sub ******\n");printf("****** 3. mul 4. div ******\n");printf("****** 0. exit ******\n");printf("**********************************\n");
}int main()
{int input = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case SUB://break;case ADD:break;case MUL:break;case DIV:break;case EXIT:printf("退出\n");break;default:printf("选择错误,重新选择\n");break;}} while (input);return 0;
}
三、联合体
(一)联合体的储存
我们直接将联合体的储存是因为他和结构体上面就一个本质差别:联合体成员公用同一块空间(所以联合也叫共用体)。
规则:
1、联合的大小至少是最大成员的大小。
2、当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。


(二)联合体的应用
联合体和结构体嵌套使用,可以节省很多内存:

例如我们需要使用该结构体,如果前面三个公共属性必选,而特征属性非必选,我们可以设置下面的代码来减少结构体的内存:

四、结束语
到此这篇文章就告一段落了,小编还会继续用心对待每一篇文章,与大家一起进步,非常有幸能得到大家的支持!

相关文章:
C语言:自定义类型进阶(结构体、联合体、枚举)
自定义类型(结构体、联合体、枚举) 一、结构体(一)结构体的内存对齐1、结构体内存对齐规则(1)引子(2)offsetof 宏函数(3)内存对齐原理(4ÿ…...
SPSSAU | 最好最差权重BWM原理及案例实操分析
BWM(best-worse-method,最好最差法)是一种多准则决策方法,由Jafar Rezaei于2015年提出,其通常用于确定决策标准的权重。其原理是比如5个指标,如果以前AHP就需要5个指标两两的相对重要性数据。但是现在简化为…...
docker安装elasticsearch(es)最新版本
docker安装elasticsearch(es) docker官网 https://hub.docker.com/ https://www.cnblogs.com/balloon72/p/13177872.html 1、拉取最新项目elasticsearch docker pull elasticsearch:8.14.3lscpu 查看架构 2、构建环境 mkdir -p /data/elasticsear…...
02 RabbitMQ:下载安装
02 RabbitMQ:下载&安装 1. 下载&安装1.1. 官网1.2. Docker方式1.2.1. 下载镜像1.2.2. 启动1.2.3. 登录验证 1. 下载&安装 1.1. 官网 RabbitMQ: One broker to queue them all | RabbitMQ 1.2. Docker方式 1.2.1. 下载镜像 # docker pull 镜像名称[…...
mmcv库出现No module named ‘mmcv._ext
遇到 "No module named mmcv._ext" 这个错误通常意味着你的 Python 环境中缺少 mmcv 库的扩展模块 _ext。mmcv(MMDetection 训练工具箱的核心库)通常依赖于 _ext 模块来提供一些高性能的操作,这些操作是用 C/C 实现的,并…...
防止xss(跨站脚本攻击)
1、输出数据时进行转义:这是最基本的预防措施。确保在输出数据到HTML时对特殊字符进行适当的转义,以防止它们被解释为HTML或JavaScript代码。PHP中可以使用htmlspecialchars()、strip_tags()、htmlentities函数来实现这一点。 echo htmlspecialchars($d…...
django小型超市库存与销售管理系统-计算机毕业设计源码46608
摘 要 随着信息技术的快速发展,超市库存与销售管理面临着前所未有的挑战与机遇。为了提升超市的运营效率,优化库存管理,并增强销售数据的分析能力,我们基于Django框架设计并开发了一套小型超市库存与销售管理系统。该系统充分利用…...
项目实战_表白墙(简易版)
你能学到什么 一个比较简单的项目:表白墙(简易版),浏览器:谷歌升级版将在下个博客发布 效果如下 正文 说明 我们是从0开始一步一步做这个项目的,里面的各种问题,我也会以第一人称视角来解…...
优化 Spring Boot 项目启动速度:高效管理大量 Bean 注入
个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119@qq.com] 📱个人微信:15279484656 🌐个人导航网站:www.forff.top 💡座右铭:总有人要赢。为什么不能是我呢? 专栏导…...
《LeetCode热题100》---<5.普通数组篇六道>
本篇博客讲解LeetCode热题100道普通数组篇中的六道题 第一道:最大子数组和(中等) 第二道:合并区间(中等) 第一道:最大子数组和(中等) 法一:贪心算法 class So…...
【Hot100】LeetCode—169. 多数元素
目录 题目1- 思路2- 实现⭐169. 多数元素——题解思路 3- ACM 实现 题目 原题连接:169. 多数元素 1- 思路 定义两个变量 一个是 count:维护当前元素的出现次数一个是 ret :维护当前元素 思路 遍历整个数组**①如果 count 0 **ÿ…...
专科、本科、研究生是按照什么分类的?
高等教育按照阶段主要分为以下几类 一、专业学位教育 特点:职业导向 专业学位教育是针对特定职业领域的专业培训,如医学、法律、工程等,旨在使学生具备从事相关职业所需的专业知识和实践技能。 实践性 专业学位教育注重实践教学和职业技…...
关于实时ODS层数仓搭建的三个问题
目录 问题一:数据同步的实时性无法满足 问题二:批量数据同步计算处理效率低 问题三:没有稳定的数据传输管道 FineDataLink的解决方案 实战案例-销售部门与财务部门数据同步 设置ODS层实时同步任务 设置DW层增量数据同步 设置 DM 层任务汇总 关…...
微信仿H5支付是什么
仿H5支付是指一种模拟原生H5支付流程的非官方支付方式。这种支付方式通常是由第三方支付服务提供商开发和维护的,目的是为了绕过官方支付渠道的限制,如费率、审核等问题。然而,由于仿H5支付并非官方授权和认可的支付方式,其安全性…...
网络安全知识竞赛规则及流程方案
为普及网络安全知识,进一步提升网络安全意识,树立正确的网络安全观,营造安全健康文明的网络环境,在2023年国家网络安全宣传周到来之际,特举办网络安全知识有奖竞赛活动,通过竞赛活动普及国家法律法规、政策…...
赞!蚓链用数字化打造助农扶农电商平台!
助农扶农电商平台在推动农村经济发展、促进农民增收方面发挥着重要作用。蚓链数字化平台使用“防伪溯源”为农户、商户、平台、政府与消费者打造了全方位的信任链条和纽带。给各方带来众多价值! (一)农户方面 1、拓宽销售渠道,降…...
RocketMQ延时消息
RocketMQ消息发送基本示例(推送消费者)-CSDN博客 RocketMQ消费者主动拉取消息示例-CSDN博客 RocketMQ顺序消息-CSDN博客 RocketMQ广播消息-CSDN博客 延时消息: 延时消息实现的效果就是产者调用 producer.send 方法后,消息会立即发送到 Broker,并被存…...
【C++/STL】:哈希的应用 -- 位图布隆过滤器
目录 🚀🚀前言一,位图1. 位图的概念2. STL库中的位图3. 位图的设计4. 位图的模拟实现5. 位图的优缺点6. 位图相关考察题⽬ 二,布隆过滤器1. 布隆过滤器的概念2. 布隆过滤器的实现3. 布隆过滤器删除问题4. 布隆过滤器的优缺点 点击…...
非线性面板数据实证模型及 Stata 具体操作步骤
目录 一、引言 二、文献综述 三、理论原理 四、实证模型 五、稳健性检验 六、程序代码及解释 一、引言 在当今的经济和社会研究中,非线性面板数据模型的应用日益广泛。这类模型能够更好地捕捉数据中的复杂关系,为研究者提供更深入和准确的分析结果。…...
视角 | 麻省理工学院提出出温度计校准法,专治AI大模型过度自信
在数字化浪潮的推动下,人工智能(AI)正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展,捕捉行业动态;提供深入的新闻解读,助您洞悉技术背后的逻辑;汇聚行业专家的见解,…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
ubuntu中安装conda的后遗症
缘由: 在编译rk3588的sdk时,遇到编译buildroot失败,提示如下: 提示缺失expect,但是实测相关工具是在的,如下显示: 然后查找借助各个ai工具,重新安装相关的工具,依然无解。 解决&am…...
