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

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

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

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

                                                                                                       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.mzph.cn/news/781651.shtml

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

相关文章

Mybatis在SpringBoot中是如何被加载执行

首先依赖于springboot的自动装配EnableAutoConfiguration注解&#xff0c;这个注解最终帮助我们读取mybatis-spring-boot-autoconfigure-x.x.x.jar中的META-INF\spring.factories配置类&#xff1a; org.springframework.boot.autoconfigure.EnableAutoConfiguration\ org.myb…

Mysql数据库——阻塞语句查询与分析

目录 前言 阻塞语句查询与分析 Show Processlist——查看每个与数据库连接的session状态 非Sleeping状态进程数 执行时间较长进程号 查看当前运行的所有事务 当前锁 被blocking阻塞的事务数 数据库连接数 查看锁状态 正在被使用的表 前言 MySQL阻塞是指并发访问时&…

LInux|命令行参数|环境变量

LInux|命令行参数|环境变量 命令行参数main的参数之argc&#xff0c;argv几个小知识<font color#0099ff size 5 face"黑体">1.子进程默认能看到并访问父进程的数据<font color#4b0082 size 5 face"黑体">2.命令行创建的程序父进程都是bash 环…

微分方程错题本

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

【图像超分】论文精读:Image Super-Resolution Using Dense Skip Connections(SRDenseNet)

第一次来请先看这篇文章:【超分辨率(Super-Resolution)】关于【超分辨率重建】专栏的相关说明,包含专栏简介、专栏亮点、适配人群、相关说明、阅读顺序、超分理解、实现流程、研究方向、论文代码数据集汇总等) 文章目录 前言Abstract1. Introduction2. Related work2.1. S…

解释TCP和UDP之间的区别

解释TCP和UDP之间的区别 TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;是两种在网络中广泛使用的传输层协议&#xff0c;它们各自具有独特的特点和适用场景。下面将详细解释TCP和UDP之间的区别&#xff0c;并从多个维度进行对比。 连…

设计模式(4):建造者模式

一.场景 我们要建造一个复杂的产品,比如手机、电脑、汽车。这个复杂的产品的创建。有这样一个问题需要处理&#xff1a; 装配这些子组件是不是有个步骤问题&#xff1f; 实际开发中&#xff0c;我们所需要的对象构建时&#xff0c;也非常复杂&#xff0c;有很多步骤需要处理时…

【Qt】:信号与槽(二)

信号与槽 一.带参数的信号和槽二.信号与槽的多对多连接三.信号与槽的断开四.lamda表达式定义槽函数 一.带参数的信号和槽 Qt的信号和槽也⽀持带有参数,同时也可以⽀持重载.此处我们要求,信号函数的参数列表要和对应连接的槽函数参数列表⼀致.&#xff08;一致指的是类型一致&a…

【算法笔记】 树形DP算法总结

定义&#xff1a;树形DP也叫树状DP&#xff0c;即在树上进行的DP&#xff0c;是DP中较为复杂一类 1&#xff1a;主体 即like拓扑排序&#xff0c;从叶子节点向上更新其父节点&#xff0c;从而进行dp&#xff0c;确保先更新的子节点去更新其父节点&#xff0c;一般使用dfs形式…

mysql安装遇到的问题

最近mysql安装遇到了许多问题 这个界面是下载器界面&#xff0c;reconfigure是重新配置这个版本&#xff0c;要新安装要点add 进入这个界面选择对应的版本下载

面试题库二

1、简述TCP/IP的三次握手和四次挥手 TCP&#xff08;Transmission Control Protocol&#xff09;是一种可靠的、面向连接的传输层协议&#xff0c;用于在网络中传输数据。在建立连接和断开连接时&#xff0c;TCP 使用了三次握手和四次挥手来确保通信的可靠性和正确性。 三次握手…

【C语言】作用域规则

任何一种编程中&#xff0c;作用域是程序中定义的变量所存在的区域&#xff0c;超过该区域变量就不能被访问。C语言中有三个地方可以声明变量&#xff1a; 在函数或块内部的局部变量在所有函数外部的全局变量在形式参数的函数参数定义中 局部变量 在某个函数或块的内部声明的…

MySQL 数据库基础操作详解

文章目录 MySQL 数据库基础操作详解1. 基本概念2. 库的操作3. 表的操作4. 数据操作5. 示例示例一&#xff1a;创建表和插入数据示例二&#xff1a;查询数据示例三&#xff1a;更新数据示例四&#xff1a;删除数据 MySQL 数据库基础操作详解 MySQL 是一种常用的关系型数据库管理…

【目录整理】(五)

​​​​​Git 基础 Git 详细安装教程文章浏览阅读10w次&#xff0c;点赞9.6k次&#xff0c;收藏1.7w次。Git 是个免费的开源分布式版本控制系统&#xff0c;下载地址为git-scm.com 或者 gitforwindows.org&#xff0c;本文介绍 Git-2.40.0-64-bit.exe 版本的安装方法&#x…

京准 | NTP网络时钟系统(子母钟系统)设计与答疑

京准 | NTP网络时钟系统&#xff08;子母钟系统&#xff09;设计与答疑 京准 | NTP网络时钟系统&#xff08;子母钟系统&#xff09;设计与答疑 子母钟系统&#xff0c;顾名思义就是由1/2套母钟和一群子钟组成。如果你选择了安徽京准公司的HR系列时钟系统产品&#xff0c;那么…

python电商结合双轨制

最近又重新整合翻看以前的数据&#xff0c;图片&#xff0c;绘画&#xff0c;还有各种编程代码&#xff0c;python,leetcode,还有关于商业方面的一些见解,想起了大学时候和同学们并肩作战&#xff0c;熬夜编码的时光。还有大数据&#xff0c;八爪鱼爬虫。 下面是我的手稿电商打…

算法学习——LeetCode力扣动态规划篇9

算法学习——LeetCode力扣动态规划篇9 1035. 不相交的线 1035. 不相交的线 - 力扣&#xff08;LeetCode&#xff09; 描述 在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在&#xff0c;可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线&#x…

JavaSE day16笔记 - string

第十六天课堂笔记 学习任务 Comparable接口★★★★ 接口 : 功能的封装 > 一组操作规范 一个抽象方法 -> 某一个功能的封装多个抽象方法 -> 一组操作规范 接口与抽象类的区别 1本质不同 接口是功能的封装 , 具有什么功能 > 对象能干什么抽象类是事物本质的抽象 &…

2536. 子矩阵元素加 1

跳转题目 本题暴力可以做&#xff0c;猜到用差分&#xff0c;但是不熟&#xff0c;不知道二维差分怎么用&#xff0c;碰到用差分的题目太少了。 暴力算法&#xff1a; class Solution { public:vector<vector<int>> rangeAddQueries(int n, vector<vector<…

Docker 部署 FRP 内网穿透 实现端口映射

Frp 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、HTTPS 等多种协议&#xff0c;且支持 P2P 通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。 官网地址&#xff1a;https://github.com/fatedier/frp 准备工作…