位段(域)机制——结构体的特殊实现

简介: 正片开始👀概念🤔什么是位段?

正片开始👀

概念🤔

什么是位段?

位段又称为位域,C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员就叫做称为位段( bit field) 。利用位段能够用较少的位数存储数据达到节省空间的目的。


位段是结构体特有的,所以声明是和结构是类似的,但有两个不同:

1. 位段成员必须是 int ,unsigned int,signed int

2. 位段成员名后边结构包括一个冒号和整型数字

举个栗子:

struct haha
{
    unsigned int ch   : 8;    //8位
    unsigned int chh : 6;    //6位
    unsigned int chhh : 18;   //18位
};
struct haha dest;

内存分配🤔

这里的 haha 就是一个位段的类型,这个神神秘秘的位段咱不常见,那么他的大小怎么算的呢?其实和结构体是一样的:

struct arr
{
int a:2;
int b:5;
int c:10;
int d:30;
};
int main()
{
printf("%d\n",sizeof(struct arr));
return 0;
}

image.png

这里 a:2什么意思呢?

成员 a 只占 2 个比特位,后面同理,既然这样,那我们总计 47 比特位,也就是 6 个字节 48 个比特位已经足够了,那为什么又是 8 呢?位段的内存分配到底是怎样的?


这里千万不要犯低级错误误认为他的大小就是 47 个比特位,和前一篇博客叙述原理相同,因为都是 int 类型,所有成员会向 int 看齐,int 是四字节,默认 8 字节,对齐数取 4 字节,a+b < 1字节,合并申请 1 字节空间,后面都需要独立申请空间,总计 1+2+4 = 7字节,结构体大小必须是最大对齐数整数倍,取 4 的整数倍就是 8,因此为 8 字节。


位段跨平台问题🤔

我们细想刚刚这种机制,a,b,c,d 分别为 2,5,10,30 比特位,而我一个字节是 8 个比特位,假若在给 a 分配了 1 字节后,还剩 6 比特位,这 6 个位子我要不要让给二哥 b 成员来享用呢?==我是一字节一字节榨干资本还是出手阔绰安排"单人房"呢?==这里就有了歧义。


要知道位段在空间上是按照需要以四字节 int 或一字节 char 的方式来开辟空间,他涉及很多的不确定性因素,这就是为什么位段是不跨平台的,注重可移植性的程序应该避免使用位段。


有什么不确定因素呢,就好比我们刚刚提到的内存分配问题,这个问题连C语言标准都没有规定我到底该怎么利用,需要由具体的编译器环境决定,编译器环境又依赖于不同的平台比如 Linux 是 gcc 标准,VS则是 windows 标准。


我们要知道:👏👏

1. int 位段被当成有符号数还是无符号数是不确定的。

2. 位段中最大位的数目不能确定(16位机器最大 16,32 位机器最大 32)。

3. 位段中成员的内存从左到右分配还是从右向左分配标准尚未定义。

4. 当一个结构中包含两个位段时,第二个位段成员比较大,无法容纳第一个位段剩余的位时,是应当舍弃还是利用,标准尚未定义。


作用🤔

“ 这么个玄乎的玩意儿拿来干嘛啊 ”你可能会有这样的疑问


我们拿上面的情景来分析一手:


int a:2;

int b:5;

int c:10;

int d:30;

我们不分配位段时,需要 16 个字节,分配后只要 8 个字节,其实位段就是为了节省空间,充当个省流大师。


位段使用的前提条件就是某些细节需要非常明确,假如我成员 a 的取值只有四种状态:00,01,10,11,那我给 a 分配 2 个字节是不是就足够了,那我就给 2 个,我如果一上手啪叽就是一个 int 类型,32 个字节横空出世,这个节省的性价比可不低哦~


当然万事万物不可能十全十美,我帮你节省但总归会有一定浪费,这是不可避免的。总结一下就是位段跟结构相比,可以达到相同效果且可以有效节省空间,但存在跨平台问题存在。

image.png

这就是我们在互联网上向某个对象发送信息的原理,里面最大的问题就是这个包如果直接扔到网上去,就会像拖拉机上高速,铁铁的堵车造成网络拥挤,我们就会利用位段机制进行适当缩减以减小网络的负担。

相关文章
|
4月前
|
存储 安全 C语言
C语言深度解析:函数指针的底层本质与避坑指南
本文深入剖析C语言函数指针的本质——函数名即代码段入口地址,厘清其与数据指针的根本差异;系统梳理回调、跳转表、中断向量、动态库等核心应用场景;重点警示签名不匹配、`void*`强转、野指针调用三大致命陷阱,并给出`typedef`封装、空值校验、边界防护等最佳实践。(239字)
699 134
|
4月前
|
存储 安全 算法
C语言高频错误实例对比:8段代码帮你避开90%的坑
本文精选8组典型C语言错误与正确代码对比,直击数组越界、字符串溢出、野指针、内存泄漏、有无符号混用、返回局部地址、sizeof误用、未定义行为等高频陷阱,以实例培养安全编码直觉。(239字)
|
4月前
|
缓存 编译器 程序员
C语言深度解析:restrict关键字——编译器性能优化的终极钥匙
C99的`restrict`关键字是C语言性能优化的“终极钥匙”:它向编译器承诺指针独占访问内存,彻底解决同类型指针别名问题,解锁循环向量化、寄存器缓存等激进优化。滥用致未定义行为,善用则性能飙升数倍——这才是真正高阶C程序员的必修课。(239字)
|
4月前
|
存储 网络协议 安全
C语言深度解析:位域的底层逻辑与跨平台避坑指南
位域是C语言专为bit级内存操控设计的特性,用于嵌入式寄存器映射、协议解析等场景,可大幅节省内存。但其布局受编译器、字节序、对齐规则影响,存在有符号陷阱、跨平台不一致、不可取地址等风险。慎用,优先选unsigned int,跨平台务必改用位运算。
|
5月前
|
存储 缓存 安全
C语言深度解析:volatile 关键字——编译器优化的「禁区」
`volatile`是C语言中被严重低估却至关重要的关键字:它不改变存储位置,而是强制编译器禁用优化,确保每次访问都直读/写内存——用于硬件寄存器、中断变量、多线程共享数据等场景,是嵌入式与驱动开发正确性的基石。(239字)
|
存储 网络安全 开发工具
【随笔】Gitee -- Gitee仓库创建 & SSH公钥生成 (二)
【随笔】Gitee -- Gitee仓库创建 & SSH公钥生成 (二)
|
存储 编译器
一文轻松理解内存对齐(2)
一文轻松理解内存对齐
321 0
|
前端开发 索引 Python
Sphinx和rst在科研笔记和学术博客中的高效用法
我们从小开始接触计算机的方式就让我们陷入了一种怪圈儿,比如操作系统只会用Windows、码字只知道word而且相信大多数人到现在依然还用不好、处理简单的文本表格只知道用excel。这些工具当然很好,也很强大,而且使用门槛低,也是广大人民日常工作中的必备工具。
1813 0
|
2天前
|
人工智能 运维 数据挖掘
最新版通义千问(Qwen3.8-Max-Preview)功能介绍
2026年7月,阿里云通义千问正式对外开放**Qwen3.8-Max-Preview旗舰预览模型**,作为目前千问系列规格最高、综合性能最强的新一代万亿级AI模型,该模型搭载2.4T超大参数架构,是阿里云首款突破万亿参数的原生多模态旗舰模型,全面覆盖文本、图像、视频、文档多维度处理能力。相较于前代热门Qwen3.7-Max版本,本次预览版实现全方位跨越式升级,在真实工程开发、多智能体长周期任务、全链路办公自动化、海量数据分析等高阶场景中,综合能力已达到全球顶尖模型水准。现阶段该模型已正式开放抢先体验通道,依托阿里云百炼Token Plan、Qoder编码平台、QoderWork办公终端三大专属
1809 0