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科技的最新发展,捕捉行业动态;提供深入的新闻解读,助您洞悉技术背后的逻辑;汇聚行业专家的见解,…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...