系列文章目录
🎈 🎈 我的CSDN主页 :OTWOL的主页,欢迎!!!👋🏼👋🏼
🎉🎉我的C语言初阶合集 :C语言初阶合集,希望能帮到你!!!😍 😍
🔍🔍我的C语言进阶合集 :我的C语言进阶合集,期待你的点击!!!🌈🌈
文章目录
前言
各位博友,大家好呀!👋 今天我给大家带来的是对C语言位段部分的全面总结📚,
从位段的基本概念讲起,到其语法规则、实战技巧,再到需要留意的细节,一应俱全📝。
保证让初学者也能循序渐进,轻松上手!哈哈哈哈哈!!!😁
一、位段的定义
位段(Bit field)是C语言中的一种数据结构,它允许程序员在一个结构体中以位为单位来指定其成员所占的内存长度。
这种以位为单位的成员称为"位段"或"位域"。
位段的基本单位是比特位(bit
),而不是字节(byte
)。
位段的主要目的是节省内存空间,特别是在需要存储小于 一个字节的数据时。
二、位段的语法
位段的定义要借助于 结构体,
- 语法如下:
c
struct 标签名
{
类型 成员名 : 宽度; // 类型是基础类型(int、unsigned int、signed int、char等),宽度是成员所占的位数
};
类型:
必须是整型(
int
、signed int
、unsigned int
)或char
类型,不能是浮点型或指针。
成员名:
是位段的名称。
宽度:
成员所占的位数,范围为
0
到sizeof(类型) * 8
。
三、位段的具体使用
(1)声明位段:
c
struct A
{
int _a : 2;
int _b : 5;
int _c : 10;
int _d : 30;
};
A就是⼀个位段类型。
那位段A所占内存的大小是多少?
c
#include<stdio.h>
// 定义一个名为 A 的结构体,包含 四个位字段
struct A
{
int _a : 2; // _a字段占用 2位
int _b : 5; // _b字段占用 5位
int _c : 10; // _c字段占用 10位
int _d : 30; // _d字段占用 30位
};
int main()
{
// 打印struct A的大小,使用 %zd 格式化输出 size_t 类型的值
printf("%zd\n", sizeof(struct A));
return 0;
}
- 输出结果:
(2)使用位段:
c
#include <stdio.h>
// 定义一个结构体A,包含四个位段(bit fields),每个位段占用不同数量的比特位。
struct A
{
// _a位段占用 3位
char _a : 3;
// _b位段占用 4位
char _b : 4;
// _c位段占用 5位
char _c : 5;
// _d位段占用 4位
char _d : 4;
};
int main()
{
// 创建一个 A类型的变量 a,并初始化为 0
struct A a = { 0 };
// 给_a位段赋值 10,由于_a只有 3位,所以会截断最高位的 1,只保留 010
a._a = 10;
// 给_b位段赋值 12,由于_b有 4位,12的二进制为 1100,可以直接放入
a._b = 12;
// 给_c位段赋值 3,由于_c有 5位,3的二进制为 11,会在高位补 0,变成 00011
a._c = 3;
// 给_d位段赋值 4,由于_d有 4位,4的二进制 100,会在低位补 0,变成 0100
a._d = 4;
// 以下是对内存布局的注释说明
// 假设位段分配的内存中的比特位是从右向左使用的,如果分配的比特位不够使用,剩余的内存会被浪费掉
// 由于机器是小端存储,所以内存上应该是:62 03 04(十六进制表示)
// 打印 struct A 的大小,使用 %zd 格式化输出 size_t 类型的值
printf("%zd\n", sizeof(struct A));
//打印结构体 a 的地址
printf("%p\n", &a);
return 0;
}
- 输出结果:
- 内存分布示例:
补充:
一个 十六进制数要用 四个 二进制数来表示
四、位段的注意事项
(1)内存分配:
位段的空间是按照需要以4个字节(
int
)或者1个字节(char
)的方式来开辟的。
位段中的成员可能并不是每个都独自占1个字节的空间,
所以直接取某个成员的地址是没有意义的(一个字节内部的bit
位是没有地址的)。
位段分配的内存中的比特位是从左向右使用还是从右向左使用,
以及分配剩余的比特位不够使用时是继续使用还是浪费掉,
这些标准都尚未定义,取决于具体的编译器和平台。
(2)跨平台问题:
位段的具体布局(如位的排列顺序)在不同的平台和编译器之间可能存在差异,因此可能影响代码的可移植性。
位段的成员使用无符号类型通常更安全,因为符号位的处理在不同平台和编译器下可能不一致。
(3)赋值和访问:
赋值给位段时,如果值超出了位段能表示的范围,那么多余的高位会被截断。
访问位段时,注意不要超出了所定义的位段大小。
(4)数据类型一致性:
位段里的成员类型要尽量保持一致,否则可能会带来不必要的麻烦和不确定性。
(5)性能问题:
位段的跨域访问(例如,跨越字节边界)的性能可能低于单一数据块的访问。
总结
- 位段的优点:
能够精确地控制成员所占的内存长度,从而节省空间;在需要处理 位级数据 时非常方便。
- 缺点:
跨平台性和可移植性差;
内存分配和存储方式可能因编译器和平台的不同而有所差异;
使用不当可能导致未定义行为。
- 使用场景:
适用于需要 精确控制内存占用 和 处理位级数据 的情况,
如硬件编程、网络通信协议等。
END
每天都在学习的路上!
On The Way Of Learning