什么是位段?
——位段是一种类似结构体的类型。
位段的声明和结构体类似,但有两点不同:
- 位段的成员必须是int、unsigned int或signed int(可能也有char,但是一个位段的类型必须是类似的)
- 位段的成员名后边有一个冒号和一个数字(意思是这个变量需要多少个比特位)
位段的内存分配
- 位段的成员可以是int、unsigned int、signed int或者是 char类型
- 位段的空间上是按照需要以4个字节(int)或1个字节(char)的方式来开辟的
- 位段涉及很多不确定因素,不跨平台,注重可移植性程序不使用位段
1234567891011121314 | //位段 - 二进制位struct S{ int a : 2;//需要2个比特位 int b : 5;//需要5个比特位 int c : 10;//需要10个比特位 int d : 30;//需要30个比特位};int main() { struct S s; printf("%d\n",sizeof(s));//8 return 0;} |
打印的结果是s使用8字节空间。
首先开辟一个4字节的空间,共32bit,先给a,b,c分配共17bit的空间,剩下的空间不够给d分配30bit的空间,剩余空间丢弃。
另开辟一块4字节的空间,共32bit,给d分配30bit的空间,剩下2bit的空间丢弃,所以位段s占8字节。
注意⚠️:位段后面的数字不能大于32。
123456789101112131415161718 | struct S{ char a : 3; char b : 4; char c : 5; char d : 4;}; int main(){ struct S s ={0}; s.a = 10;//10的二进制是1010,但a这个空间只存的下3个比特位,只能存的下010,也就是2 s.b = 20;//20的二进制是10100,b只有4比特位,存0100。 s.c = 3; s.d = 4; return 0;} |
位段的跨平台问题
位段不跨平台,主要由下面四点导致:
- int位段被当成有符号还是无符号数是不确定的。
- 位段中最大位的数目不能确定。(16位机器最大16,32位机最大32,写成27,在16位机器会出问题。)
- 标准未定义位段在内存中的分配规则,不知道从左往右还是从右往左分配
- 一个结构包含两个位段,第二个成员较大时,无法容纳第一个位段剩余位时,剩下的空间舍弃或保留不确定。