C语言结构体如何实现位段
欢迎拜访:雾里看山-CSDN博客
本篇主题:C语言结构体如何实现位段
发布时间:2025.1.13
隶属专栏:C语言
目录
- 什么是位段
- 如何实现
- 如何访问内部成员
- 位段的内存分配
- 主要应用
- 注意事项
- 可移植性问题
- 位段不能取地址
- 位段的长度限制
什么是位段
**位段(bit-filed)**是一种特殊的数据结构, 它允许在一个或者多个字节中以位为单位来指定成员的长度。位段的主要目的是更紧凑的存储数据,在某些情况下可以节省存储空间。
位段的声明和结构体是类似的,但是有两个不同。
- 位段的成员必须是
int, unsigned int和signed int
- 位段的成员名后面有一个冒号和数字。(数字表示二进制位)
如何实现
struct A
{
int _a : 2;
int _b : 5;
int _c : 10;
int _d : 30;
};
编译器会根据上面的定义将这些变量正确的存储到内存对应的位置中。
如何访问内部成员
位段内部成员的访问和结构体的访问是一样的。使用点操作符.
对内部成员进行访问。
struct A
{
int _a : 2;
int _b : 5;
int _c : 10;
};
int main()
{
struct A a;
a._a = 2;
a._b = 5;
return 0;
}
编译器会根据上面的定义将这些值正确的存储到内存对应的相应位中。
位段的内存分配
- 位段的成员可以是
int, unsigned int, signed int
或者是char
(部分编译器支持)类型。 - 位段的空间是按照需要以4个字节(
int
)或者一个字节(char
)的方式来开辟的。 - 位段涉及很多的不确定因素,位段是不跨平台的, 注重可移植性的代码应该避免使用位段。
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;
主要应用
在网络协议或者嵌入式系统等对存储空间极其严苛的环境中非常有用。
例如:计算机网络的IP
协议。
在操作硬件设备寄存器时,很多寄存器的位有不同的功能, 位段可以方便地将寄存器的各个功能位映射到结构体成员中。
例如在单片机的定时器/计数器寄存器里, 可能存在控制位(如启动/停止,计数模式位)和状态位(如溢出标志位,比较标志位),可以使用位段结构体来清晰的表达这些位,方便对硬件进行编程。
注意事项
可移植性问题
- int位段被当成有符号还是无符号是不确定的。
- 位段中最大位的数目是不能确定的。大于最大数目会出问题(16位机器中最大为16,32位机器中最大为32)。
- 位段中的成员从左向右分配还是从右向左分配是标准库中没有定义的。
- 当一个结构体包含两个以上的位段成员,第二个成员较大,无法容纳第一个成员剩余位段时,是舍弃剩余还是利用,这也是不确定的。
位段不能取地址
因为位段的存储方式的特殊性,所以C语言标准规定不可以对位段进成员使用&
运算符进行取地址操作。例如&s.a
在编译器中会直接报错。
位段的长度限制
位段成员的类型通常是int, unsigned int
等整数类型,其长度受限于基本的整形类型长度。16位机器中最大为16,32位机器中最大为32。
位段的长度是一个非负的整数常量表达式,不能使用变量来定义位段的长度。
⚠️ 写在最后:以上内容是我在学习以后得一些总结和概括,如有错误或者需要补充的地方欢迎各位大佬私信我交流!!!