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

2024-03-30 21:20

本文主要是介绍自定义类型(二)结构体位段,联合体,枚举,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

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

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

                                                                                                       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.chinasem.cn/article/862609

相关文章

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

使用Java实现通用树形结构构建工具类

《使用Java实现通用树形结构构建工具类》这篇文章主要为大家详细介绍了如何使用Java实现通用树形结构构建工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录完整代码一、设计思想与核心功能二、核心实现原理1. 数据结构准备阶段2. 循环依赖检测算法3. 树形结构构建4. 搜索子

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

如何自定义Nginx JSON日志格式配置

《如何自定义NginxJSON日志格式配置》Nginx作为最流行的Web服务器之一,其灵活的日志配置能力允许我们根据需求定制日志格式,本文将详细介绍如何配置Nginx以JSON格式记录访问日志,这种... 目录前言为什么选择jsON格式日志?配置步骤详解1. 安装Nginx服务2. 自定义JSON日志格式各

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

基于Spring实现自定义错误信息返回详解

《基于Spring实现自定义错误信息返回详解》这篇文章主要为大家详细介绍了如何基于Spring实现自定义错误信息返回效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录背景目标实现产出背景Spring 提供了 @RestConChina编程trollerAdvice 用来实现 HTT

Python如何查看数据的类型

《Python如何查看数据的类型》:本文主要介绍Python如何查看数据的类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python查看数据的类型1. 使用 type()2. 使用 isinstance()3. 检查对象的 __class__ 属性4.