一、声明
位段是基于结构体的
位段的出现是为了节省空间的,位段的声明和结构体是类似的,但是有两个不同:
1.位段的成员必须是int,unsigned int或signed int,在C99中,位段成员的类型也可以是其他类型(如char)
2.位段的成员名后有一个:和一个数字
每一个成员冒号后面的数字,代表该成员在内存中占用的二进制位大小(<=32bit)
struct A
{
int a : 2;
int b : 3;
int c : 4;
int d : 5;
};
二、内存分配
1.位段的成员是int,unsigned int,signed int或者char类型
2.位段的空间是按需以四个字节(int)或者一个字节(char)的方式来开辟的
3.位段涉及到很多不确定因素,位段不能跨平台,注重程序可移植的应避免使用位段
例:
#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;
printf("%d", sizeof(s));
return 0;
}
1.当开辟了内存后,内存中每个比特位从右向左使用还是从右向左使用是不确定的
2.下一个成员是否使用之前剩余的空间也是不确定的(当剩下的空间不足下一个成员使用的时候)
在VS2022上到底如何存储?
十进制 | 二进制 |
10 | 1010 |
12 | 1100 |
3 | 0011 |
4 | 0100 |
a存不下,到最后只能:
三、跨平台问题
1.int位段被当成有符号数/无符号数是不确定的
2.位段中最大位的数目不确定(16位机器最大的16,32位机器最大32,如果写成27,在16位机器下运行会出问题)
3.位段中的成员在内存中从左向右分配,还是从右向左分配尚未定义
4.当一个结构包含两个位段,第二个位段成员比较大,无法容纳第一个位段,剩余的位时,是舍弃剩余的位还是继续使用是不确定的
总结:同结构体相比,位段可以达到同样的效果,并且可以很好地节省空间,但是有跨平台问题存在
四、位段的应用
优点:节省空间,网络传输数据包大小较小,对网络的畅通有帮助
注意事项:位段的几个成员共有同一个字节,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位置是没有地址的(内存中每个字节分配一个地址,一个字节内部的bit位是没有地址的),所以不能对位段成员使用&操作符,这样就不能使用scnaf直接给位段的成员输入值,只能先输入放在一个变量中,然后赋值给位段的成员
//错误:
scanf("%d", &s.b);
//正确:
int b = 0;
scanf("%d", &b);
s.b = b;