📋 前言
🌈hello! 各位宝子们大家好啊,前面一章给大家带来了结构体的深层次 讲解,那么接下来就来到下一章的学习了,铁铁们准备好了嘛?
⛳️本期给大家带来的是 位段的内存分配 枚举 联合(共用体)的详细讲解让我们一起学起来把!
📚本期文章收录在《C语言进阶篇》,大家有兴趣可以看看呐!
⛺️ 欢迎铁汁们 ✔️ 点赞 👍 收藏 ⭐留言 📝!
💬 位段
⛳️一般情况下在书里,结构体的章节过来了之后就是位段(位域)叫法不同而已,说明我们的位段是靠结构体来实现的!
💬 什么是位段
位段的声明和结构是类似的,有两个不同:
- 1.位段的成员必须是 int、unsigned int 或signed int 。
- 2.位段的成员名后边有一个冒号和一个数字。(冒号后面的数字不得超过前面类型的大小.)
。
📚 代码演示:
struct A { int _a:2; int _b:5; int _c:10; int _d:30; };
⛳️ 这里A就是一个位段类型。那位段A的大小是多少?
- 会是我们心里想的16个字节嘛?
📑 代码结果:
诶这时你会发现这个结构体的内存对齐计算结构体大小完全不一样啊!为什么大小是这个呢?
- 就算是按4个整形计算也不可能是8个字节啊
- 下面我们就来介绍一下位段的内存是如何分配的!
🔥 注:结构体如何计算大小文章链接《结构体的内存对齐》
⛳️ 位段位段,说明他是位的截段 那么是什么位呢?答案是
比特位
!,每个数字是占多少个比特位
!
- 大家可以验证一下,这些数字加起来刚好32位
- 而32个
比特位
4
个字节刚好能装下- 大家看一下下面这个猜一下是不是我们计算的4呢!
struct B { int _a : 2; int _b : 5; int _c : 15; int _d : 10; };
📑 代码结果:
哦!的确是这样的。下面我们就来具体看下位段到底是怎么样开辟空间的
💭 位段的内存分配
📜说明:
- 🌱 位段的成员可以是
int
unsigned int
signed int
或者是char
(属于整形家族)类型 - 🌱 位段的空间上是按照需要以
4
个字节(int
)或者1个字节(char
)的方式来 开辟 的。 - 🌱 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
⛳️ 这些是什么意思呢?就是我们位段的成员必须是整形家族的,如果我们位段时int 类型的那么就会先开辟4个字节,不够在开辟4个字节这样一直开辟下去, char类型的也是同理!
📚 举个例子:
#include <stdio.h> struct S { char a : 3; char b : 4; char c : 5; char d : 4; }; int main() { struct S s = { 0 }; s.a = 10; s.b = 12; s.c = 3; s.d = 4; return 0; }
⛳️那么究竟是不是我们这样描述存储的实践一下看看就明白了,假设我们在vs2019 这个平台上是从低向高访问的
- 并且按照我们分配内存的慷慨性一旦放不下就重新开辟空间!
- 而我们的位段 是char 类型的说明先开辟一个字节 ,不够在开辟
- 那么我们大致画一下内存分布并运行查看一下到底是不是这样的?
🔥 注:vs2019的情况下成员存放是先从右往左用,但是内存开辟是从地地址向高地址开辟这里我们想象的大致内存分布是这样的,用了3个字节,程序运行看下是不是这样的?
📑 代码结果:
哦!看来在vs这个环境里就是按我们想像的这样开辟空间的我们在验证一下
- 我们位段的每个成员都存放数据,然后到内存里面看是不是这样存储的
- 但是每个成员只占他所对应的
比特位
存放- 所以一旦存放的内容超过所能存储的内容就会发生截断
位段成员a
在内存中占3个字节但是 10
这个数字要存放 4
个字节,所以我们就会截断
10
的二进制位是1010- 截断3位就是 010所以我们
a
存放的就是010
✅ 我们把存放进去的二进制位转成16进制来看一下!
- 因为是
16进制
所以4
个比特位 为一个16进制
!⛳️这里就可以看到按我们这存放的话,转换出来的16进制是 0x 62 03 04 00
- 我们在vs2019里面调试看一下存放的和我们一步一样!
📑图片展示:
这时就可以看出在vs2019就是按我们想的那样存储的!
- 即,位段中的成员在内存中(我们在vs是从低地址到高地址存储的)
- 一旦分配的字节不过够存放下一个成员,会开辟新的字节来存放新成员
注:但是在C语言中从左向右分配,还是从右向左分配标准尚未定义!
注:当第一个位段的剩余的内容无法存储第二个位段时,要开辟新的空间,那之前剩余的空间是否被利用取决于平台,也没有规定.
💻 位段的跨平台问题
⛳️ 跟结构相比,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。
- int 位段被当成有符号数还是无符号数是不确定的。
- 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机
器会出问题。- 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
- 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是
舍弃剩余的位还是利用,这是不确定的。