C语言自定义类型——位段
位段
目录
位段
一、定义
二、注意事项
1、位段成员必须是整型家族的(int ,unsigned int ,char 等)。
2、位段成员名后可跟冒号加一个数字来表示它占有几个比特位
三、位段的内存分配
四、具体空间开辟(截断)
五、位段的跨平台问题
C语言中有很多的自定义类型,我在以前的博客中已经讲过了结构体和结构体的内存对齐,现在我们来讲另一个自定义类型,就是位段。
一、定义
位段,C语言允许在一个结构体中以比特位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少的位数存储数据。
可以看出位段和结构体很像,下面我们引入一段代码片段来看一下位段到底长什么样子。
struct A{int a : 2;//成员a占2个比特位int b : 5;//成员b占5个比特位int c : 10;//成员c占10个比特位int d : 30;//成员d占30个比特位
};
二、注意事项
1、位段成员必须是整型家族的(int ,unsigned int ,char 等)。
可以看见,这里如果是float类型的成员,编译器会直接报错。
整型家族的数组也不行哦,编译器也会报错。
2、位段成员名后可跟冒号加一个数字来表示它占有几个比特位
正如我们在 一、定义 时的代码片段,但是其实一个位段的部分成员也可以不加冒号和数字(如果全部成员都不加冒号和数字了它就变成结构体了)。
例如上图,我们也是不会错的。
三、位段的内存分配
在window环境下的VS编译器中,位段的内存分配是按照这种规则的:根据首个成员变量的类型分配相应字节的内存(例如:首个成员是 int 类型的,则分配4个字节即32个比特位的空间大小),然后根据成员的实际大小(也就是:后面的数字)来填充这个已经分配的空间,若剩余的空间不够了,则继续根据成员类型依次分配内存并且填充(分配内存时要注意内存对齐,如果不知道什么是内存对齐,可以看我以前写的博客,填充时不用对齐),直到该位段的最后一个成员,需要注意的是,整个位段的大小是成员类型大小中最大值的整数倍。
上面的概念过于复杂,我们来看一个例子:
第一步,分配,根据第一个成员的类型分配4字节即32位大小的内存;
第二步,填充,因为a,b,c成员的大小加起来为27位,而d成员为6位,所以这块被分配的内存只能填充a,b,c(这里的填充是反向填充,即从该区域的最后端开始依次填充a,b,c);
第三步,分配,根据接下来的成员也就是 char 型的 d 分配一个字节8个比特位的空间,根据内存对齐判断,该空间紧贴上一个分配的空间即可;
第四步,填充,这块空间只够填充成员 d ;
第五步,分配,并判断内存对齐,应根据 int 型变量 e 分配4个字节的空间,但根据内存对齐这段被分配的空间不能紧挨着成员 d ,应该间隔3个字节再分配(对齐到该成员对齐数整数倍的位置上);
第六步,填充,这个空间只够填充成员 e 占用其中的30位;
第七步,根据成员 f 的 char 型分配一个字节的空间,根据内存对齐规则,该区域可以紧贴上一个区域,然后将最后一个成员填充进去;
第八步,根据内存对齐规则的最后一条,也就是整个位段的大小是成员类型大小中最大值的整数倍,所以我们必须还要在余出3个字节;
所以,位段A的内存分布情况为下图:
sizeof(struct A)=5+3+4+1+3=16字节。
下面来验证一下:
四、具体空间开辟(截断)
看一个具体的例子:
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;
由于位段的成员的大小被重新分配,例如成员 a 占3个比特位,它的范围应该是 0 到 7 ,而这里给 a 赋值为10,应该如何处理呢?这里的操作我称作为截断
请看下面我画出的内存图,更为直观
验证:这是VS中内存的部分
和我们的分析一致。
五、位段的跨平台问题
位段在不同的平台上有不同的规则:
1、int 位段被当成有符号数还是无符号数是不确定的。
2、位段中的成员从左到右分配还是从右到左分配是不确定的。
3、当一个结构包含两个位段,第二个位段成员比较大,无法容纳第一个位段剩余的位时,是舍弃剩余的位还是利用,也是不确定的。
所以跟结构体相比,位段更节省空间,但是有跨平台的问题。
这就是今天和大家分享的内容了,希望大家一起提高,共同进步!!!
C语言自定义类型——位段相关推荐
- C语言自定义类型详解
C语言自定义类型详解 一.结构体 1.结构的声明 2.特殊的声明 3.结构的自引用 4.结构体变量的定义和初始化 5.结构体内存对齐 6.修改默认对齐数 7.结构体传参 二.位段 1.什么是位段 2. ...
- 【维生素C语言】第十二章 - C语言自定义类型讲解(联合体、枚举、联合体)
原标题:自定义类型讲解?楼下保安大爷直呼内行!![C语言] 前言: 本章将对C语言自定义类型进行讲解,前期我们讲过结构体,这章将会把前面结构体还没讲完的知识继续补充. 一.结构体(struct) 结构 ...
- C语言——自定义类型(结构体,枚举,联合体,位段)
目录 结构体 结构体的定义 匿名结构体 结构体的自引用 结构体大小计算 位段 枚举 枚举概念 枚举的声明与使用 枚举大小计算 枚举与宏的区别 联合体 联合体的概念 联合体的声明与使用 联合体大小计算 ...
- C语言——自定义类型详解(结构体,联合体,枚举,位段)
专栏:C语言 个人主页:HaiFan. 专栏简介:本专栏主要更新一些C语言的基础知识,也会实现一些小游戏和通讯录,学时管理系统之类的,有兴趣的朋友可以关注一下. 结构体 前言 一.结构体 1.结构体类 ...
- 详解C语言自定义类型(结构体,位段,枚举,联合)
C语言中有许多类型,比如整形int,字符型char,双精度浮点型double等等.这些类型可以存放一些值或者字符.但是如果我想要一种类型存放一本书,显然是没有的,那么这时候就需要自定义类型了,也就是结 ...
- C语言自定义类型的介绍(结构体,枚举,联合体,位段)
⭐️前面的话⭐️ 大家好!在C语言中,有个叫"自定义类型"玩意,它究竟是什么呢?其实,就是字面意思,可以自己定义的类型就是自定义类型.具体说就是我们熟知的结构体,枚举,位段,联合体 ...
- 浅谈C语言自定义类型枚举和联合体以及对结构体位段的补充
文章目录 前言 一.结构体位段的补充说明 1.结构体位段的定义 2.位段的内存规则 3.位段的总结 2.枚举类型 1.枚举的简单介绍 3.联合体类型 1.联合体简单介绍 2.联合体存储方式 4.总结 ...
- C语言自定义类型详解!
目录 内容概述 结构体类型 结构类型的声明 结构体的特殊声明 结构体的自引用 结构体变量的定义和初始化 结构体内存对齐 结构体传参 位段 什么是位段? 位段的内存分配 位段跨平台问题 枚举类型 枚举类 ...
- C语言自定义类型——枚举类型讲解
一.枚举类型 定义:顾名思义就是一一列举,可以列举出所有常见的可能.每种可能都是常量,称为枚举常量! 把可能的取值一一列举. 比如我们现实生活中: 一周的星期一到星期日是有限的7天,可以一一列举: e ...
- C语言 自定义类型 之 【枚举】
文章目录 前言 枚举的介绍 枚举类型的定义 枚举的优点 枚举的使用 写在最后 前言 枚举在我们平时练习或学习的时候可能不是很常用,但是其在工程项目里,还是比较常见的,因为他能起到优化用.并且,有时我们 ...
最新文章
- F5 bigip.conf配置问题
- 为什么Python是数据科学领域最受欢迎的语言
- 主程序与子程序不在同一程序模块中_深度解析S7200系列PLC带参数子程序用法
- hadoop高速扫盲帖,从零了解hadoop
- [codevs1105][COJ0183][NOIP2005]过河
- docker yum 安装
- vmware中NAT模式下,虚拟机与主机能ping通 为什么虚拟机不能上网
- vue 将数据保存到vuex中
- Tomcat----windows系统通过命令符“强制关闭Tomcat”
- Cache 应用程序数据缓存
- AspNetPager分页控件教程
- 软件项目管理 实验二
- HTML排版一首古诗,古诗句排版正确方式
- word论文排版和写作02:插入算法的伪代码
- 从DDPM到DDIM:深入解读《Denoising Diffusion Implicit Models》
- 【Webpack5笔记】Webpack高级配置---提升开发体验
- 多巴胺所表达的prediction error信号
- 苹果微信多开_一个手机能登两个微信吗
- Uncaught ReferenceError: is not defined at HTMLAnchorElement.onclick
- Jetson Nano 开机程序自启动