自定义类型(二)结构体位段,联合体,枚举

news2024/11/27 2:47:51

这周一时兴起,想写两篇文章来拿个卷吧,今天也是又来写一篇博客了,也是该结束自定义类型的学习与巩固了。

常常会回顾努力的自己,所以要给自己的努力留下足迹。

为今天努力的自己打个卡,留个痕迹吧

                                                                                                       2024.03.30     小闭


目录

结构体默认对齐数的修改

结构体的实现位段

联合体

联合体的实际使用

枚举类型


结构体默认对齐数的修改

在别的编译器可能没有,但在VS中我们是可以自己修改默认对齐数的,毕竟有的编译器都没有默认对齐数,而在VS中不仅有默认对齐数还可以修改默认对齐数。那我们该如何修改结构体的默认对齐数呢,首先我们就需要认识一下这个预处理命令  #pragma。

下面就举一个代码示例吧

注:如果还没了解结构体大小如何计算的小伙伴,可以看一下这篇文章。http://t.csdnimg.cn/j7uiv

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

#pragma pack(1)    //设置默认对⻬数为1
struct S
{
	char c1;
	int i;
	char c2;
};
#pragma pack()      //取消设置的对⻬数,还原为默认
int main()
{
        
	printf("%d\n", sizeof(struct S));
	return 0;
}

现在这段代码默认对齐数已经为1了。

那我们现在就可以按照之前的步骤,来继续计算结构体的大小了。

首先因为默认对齐数为1,那么几乎所有成员的对齐数都是1了,那么这么排列下去也是没有空余的地方浪费。如图:

如图显而易见按照之前的说法,结构体大小为成员最大对齐数的整数倍那么这里把默认对齐数改为1后,导致所有的对齐数为1,而任何数都是1的倍数,所有这里结构体大小就为6.

这么一看当修改默认对齐数为1时,结构体大小其实就是所有成员大小的总和。


结构体的实现位段

 位段的声明和结构是类似的,有两个不同:

1. 位段的成员名后边有⼀个冒号和⼀个数字。

2.位段的实现要在结构体来实现

例如:

struct A
{
 int _a:2;
 int _b:5;
 int _c:10;
 int _d:30;
};

 那这代表什么呢?

那代表这位成员变量只占后面数字的bit位,如_a就只占2个bit位

1. 位段的成员可以是 int unsigned int signed int 或者是 char 等类型

2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的⽅式来开辟的。

3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

那位段是怎么存储在内存中呢?

我们再来看一段例子:

struct S
{
 char a:3;
 char b:4;
 char c:5;
 char d:4;
};
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;

 上面说到位段通常是按一个字节或4个字节开辟的,在上面的例子中是以一个字节来开辟的,

那这开辟一个字节的空间是从左到右储存还是从右到左,其实这在C语言中是没有定义的,但在VS里是从右到左的。

注意在开辟空间时:

当一个字节不足以存储下一位成员时,就会在开辟下一个字节,这里一共开辟了三个字节,所以这里结构体的大小就为3个字节

那我们在来看一下内存中存储形式是否如我所写

显然和我所写是一样的。 那位段就讲完了。


联合体

联合体与结构体一样都是自定义类型,他的成员可以是任何类型,但它与结构体不同的是,他只为成员内占用空间最大的成员开辟空间,其它成员和它共用一块空间,所以我们也叫它共用体

从上面的描述来看可能初学联合体的小伙伴可能就疑惑了,只为空间最大得成员开辟空间,那空间肯定不够给成员,那不出问题了,一开始我也这么想,但后来我才明白,联合体不像结构体,他的使用只能使用一次,在它的成员里,你只能在一次使用中选出一位成员进行赋值使用,不然就会出现错误。


联合体的大小

联合体大小上面说了其最少也要有最大成员的大小,因为其使用一次只存储一个成员,只要储存得下最大的成员那也可以把其它成员存储得下。

联合体的特点

联合体的特点就是所有成员共用一块空间。

下面用一段代码给大家看看其特点

union Un
{
	char a;
	int b;

};


int main()
{
	int a = 0x11223344;
	

	union Un un = { 0 };
	un.b = 0x11223344;
	un.a = 0x55;
	printf("%x\n", un.b);


	return 0;
}

这里我们先是给nu.b赋值0x11223344,然后再给un.a赋值0x55,然后观察其在内存中的变化,很容易发现其在un.b上的内存上改变了内存的存储,很显然其确实是一块空间共用,这样在一定程度上减少了内存的使用。 

 


联合体的实际使用

我们用一个实际情况来举例

现在要推出,⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。 每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。 图书书名、作者、页数  ,杯子设计, 衬衫:设计、可选颜色、可选尺寸

那我们就可以很容易的写出一段联合体代码解决这个问题

struct giftList
{
 int stock_number;//库存量
 double price; //定价
 int item_type;//商品类型
 
 union{
 struct
 {
 char title[20];//书名
 char author[20];//作者
 int num_pages;//⻚数
 }book;
 struct
 {
 char design[30];//设计
 }mug;
 struct
 {
 char design[30];//设计
 int colors;//颜⾊
 int sizes;//尺⼨
 }shirt;
 }item;
};

枚举类型

 枚举类型如其名,就是将东西一一列举,列举后他们就可以代表一段数字,方便我们使用。

例如:

enum en
{


	book,
	milk,
	egg,
	football

  

};

这里从上往下book代表数字0,milk代表数字1,这样往下他们这样就可以代表一个数字,这样的好处是,当我们让用户选择一个物品时,我们把枚举的成员写进代码中,当用户选择时,我们的程序就可以用一个简单的数字传回,来代表这个物品,且用户也一眼方便看出自己选择的是什么,而不是选择一个数字,然后按照数字看菜单这个数字代表什么。 

编译器也是直接显示出来给我们看,这里book就代表数字0. 


 文章已到末尾

常常会回顾努力的自己,所以要给自己的努力留下足迹。

为今天努力的自己打个卡,留个痕迹吧

                                                                                                       2024.03.30     小闭

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

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

相关文章

GitHub文件克隆到本地(GitHub desktop快速上手版)

使用 GitHub Desktop 轻松地克隆 GitHub 上的项目。 打开 GitHub Desktop 应用程序。 在菜单栏中&#xff0c;单击“文件”&#xff0c;然后选择“克隆存储库”。 在弹出的窗口中&#xff0c;选择要克隆的存储库&#xff1a; 单击与要克隆的仓库位置对应的选项卡。或者&#…

回溯算法|216.组合总和III

力扣题目链接 class Solution { private:vector<vector<int>> result; // 存放结果集vector<int> path; // 符合条件的结果// targetSum&#xff1a;目标和&#xff0c;也就是题目中的n。// k&#xff1a;题目中要求k个数的集合。// sum&#xff1a;已经收集…

【Quixel Mixer】简单介绍

一、下载 官网下载地址&#xff1a;Quixel Mixer - All-in-one texturing & material creation tool 下载好之后双击exe来安装 等待安装完成 下载后打开&#xff0c;新建一个工程和Mix 二、界面介绍 我们先将软件界面分为如下3个部分 1号区域为菜单栏 2号区域介绍 2号…

【Linux】POSIX信号量{基于环形队列的PC模型/理解信号量的出现/参考代码}

文章目录 1.POSIX信号量1.1介绍1.2接口 2.基于环形队列的PC模型2.1环形队列常用计算2.2如何设计&#xff1f;2.3如何实现&#xff1f; 3.细节处理3.1空间资源和数据资源3.2push/pop3.3理解信号量的出现1.回顾基于阻塞队列的PC模型中条件变量的使用2.如何理解信号量的投入使用&a…

数据结构:链表的双指针技巧

文章目录 一、链表相交问题二、单链表判环问题三、回文链表四、重排链表结点 初学双指针的同学&#xff0c;请先弄懂删除链表的倒数第 N 个结点。 并且在学习这一节时&#xff0c;不要将思维固化&#xff0c;认为只能这样做&#xff0c;这里的做法只是技巧。 一、链表相交问题 …

报错:ImportError: cannot import name ‘imread‘ from ‘scipy.misc‘

报错内容&#xff1a; 问题代码通常是导入scipy库的版本出现了问题。 解决方法&#xff1a; 方法一&#xff1a; scipy版本还原到1.2.0 pip install scipy1.2.0 方法二&#xff1a; 使用from imageio import imread进行替换from scipy.misc import imread 使用imageio库同…

预处理详解(二)-- 条件编译 - 头文件包含 - ##和#运算符

目录 一.##和#运算符1.#运算符&#xff08;字符串化&#xff09;2.##运算符&#xff08;粘合符&#xff09; 二.条件编译&#xff08;很重要&#xff09;三.命名约定1.宏名的命名2.函数的命名 四.#undef(用于移除一个宏定义)五.命名行约定六.头文件被包含的方式1.本地文件包含2…

推特Twitter有直播功能吗?如何用Twitter直播?

现在各大直播平台已经成为社交媒体营销的一种重要渠道&#xff0c;它让品牌能够即时地与全球受众进行互动。据统计&#xff0c;直播市场正在迅速增长&#xff0c;预计到2028年将达到2230亿美元的规模。在这个不断扩张的市场中&#xff0c;许多社交媒体平台如YouTube、Facebook、…

消息队列的七种经典应用场景

在笔者心中&#xff0c;消息队列&#xff0c;缓存&#xff0c;分库分表是高并发解决方案三剑客。 在职业生涯中&#xff0c;笔者曾经使用过 ActiveMQ 、RabbitMQ 、Kafka 、RocketMQ 这些知名的消息队列 。 这篇文章&#xff0c;笔者结合自己的真实经历&#xff0c;和大家分享…

在ROS上快速验证PID算法

在ROS上快速验证PID算法 前言 最近有在外面出差授课的工作任务&#xff0c;其中有一个环节是给大家讲述PID相关的内容&#xff0c;在制作相关PPT的时候查询了很多资料&#xff0c;但是写着写着突然意识到一个问题&#xff0c;PID已经在控制专业学习过程以及工程开发时间中那么…

量化交易入门(二十五)什么是RSI,原理和炒股实操

前面我们了解了KDJ&#xff0c;MACD&#xff0c;MTM三个技术指标&#xff0c;也进行了回测&#xff0c;结果有好有坏&#xff0c;今天我们来学习第四个指标RSI。RSI指标全称是相对强弱指标(Relative Strength Index),是通过比较一段时期内的平均收盘涨数和平均收盘跌数来分析市…

【YOLOv5改进系列(9)】高效涨点----使用CAM(上下文增强模块)替换掉yolov5中的SPPF模块

文章目录 &#x1f680;&#x1f680;&#x1f680;前言一、1️⃣ CAM模块详细介绍二、2️⃣CAM模块的三种融合模式三、3️⃣如何添加CAM模块3.1 &#x1f393; 添加CAM模块代码3.2 ✨添加yolov5s_CAM.yaml文件3.3 ⭐️修改yolo.py文相关文件 四、4️⃣实验结果4.1 &#x1f39…

HTB devvortex靶机记录

做这个靶机的师傅们我先提一句&#xff0c;不知道是否是因为网速还是其他因素影响&#xff0c;登录后台管理后&#xff0c;有大概率会被其他人挤下去&#xff0c;所以做这道题的师傅可以考虑在没人的时候去做。 打开靶场以后老规矩nmap扫一遍 这里爆出了80端口和22端口&#xf…

解决Veeam做Replication复制或备份任务并发数量少问题

Veeam执行replication复制或者备份任务时&#xff0c;一直都只有两个任务并发在跑&#xff0c;其他同时间任务只能等待前两个任务处理完才可以开始。 解决方法&#xff1a; 进入Veeam-Bacup Infrastructure-Backup Proxies&#xff0c;可以看到VMware Backup Proxy&#xff0…

【并发】第二篇 ThreadLocal详解

导航 一. ThreadLocal 简介二. ThreadLocal 源码解析1. get2. set3 .remove4. initialValue三. ThreadLocalMap 源码分析1. 构造方法2. getEntry()3. set()4. resize()5. expungeStaleEntries()6. cleanSomeSlots()7. nextIndex()8. remove()9. 总结ThreadLocalMap四. 内存泄漏…

@EnableWebMvc 导致自定义序列化器失效

目录 前言 一. 自定义序列化器失效 1.1 EnableWebMvc 的作用 1.2 EnableWebMvc 带来了什么后果 1.3 原理分析 1.4 问题解决 二. 总结 前言 在使用Swagger的时候用 到了EnableWebMvc&#xff0c;发现之前为了解决Long类型、日期类型等自定义序列化器失效了 Configurati…

TransformControls 是 Three.js 中的一个类,用于在网页中进行 3D 场景中物体的交互式操作。

demo案例 TransformControls 是 Three.js 中的一个类&#xff0c;用于在网页中进行 3D 场景中物体的交互式操作。让我们来详细讲解它的输入参数、输出、属性和方法&#xff1a; 输入参数&#xff1a; TransformControls 构造函数通常接受两个参数&#xff1a; camera&#…

企业培训系统功能介绍

在当今知识经济时代&#xff0c;企业的竞争力在很大程度上取决于员工的专业能力和综合素质。为了适应不断变化的市场需求和技术进步&#xff0c;企业需要对员工进行持续有效的培训。一个高效的企业培训系统对企业人才培训至关重要。以下介绍一下企业培训系统的主要功能&#xf…

【Qt 学习笔记】Day1 | Qt 开发环境的搭建

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Day1 | Qt 开发环境的搭建 文章编号&#xff1a;Qt 学习笔记 / 02 文…

下载huggingface中数据集/模型(保存到本地指定路径)

一. snapshot_download # 1.安装huggingface_hub # pip install huggingface_hubimport osfrom huggingface_hub import snapshot_downloadprint(downloading entire files...) # 注意&#xff0c;这种方式仍然保存在cache_dir中 snapshot_download(repo_id"ibrahimhamam…