24.0、 C语言——自定义数据类型_位段
位段:
什么是位段 ->
位段的声明和结构是类似的,但有两个不同:
1. 位段的成员必须是: int 、 undigned int 、或 signed int;
2. 位段的成员后边有一个冒号和一个数字;
3. 当然在我们查阅了大量的资料之后,可以发现不仅仅是int类型,只要是整型就行,比如short 、 char 等都可以;
4. 但是建议大家在定义成员变量的时候,尽量都是一个类型的;
实例代码 ->
struct S {
int a : 2;
int b : 5;
int c : 10;
int d : 30;
};
int main() {
struct S s = { 0 };
printf("%d\n", sizeof(s));
return 0;
}
1. 声明一个结构体 S ,定义了四个变量;
2. 在 main() 函数中输出定义的一个 结构体的对象 s 的大小,输出结果是 -> 8
3. 我们先来解释一下 ' : ' 后面的数字是什么意思 ->
变量 a ,我们认为 变量 a 赋予的数据不会太大,所以不需要分配太多的内存空间,那么我们只给他 2 个 bit位 的空间,因此变量 a ' : ' 后面的 2 代表的就是给 变量a 2 个 bit 位的内存空间;【但是要注意不能分配超过该变量字节的 bit 位数,比如说 int 类型就不能分配超过 32 位的 bit 数】
位段的内存分配:
1. 位段的成员可以是 int unsigned 、int 、 signed int 或者是 char (属于整型家族)类型;
2. 位段的空间上是按照需要以 4个字节(int)或者1个字节(char)的方式来开辟的;3. 位段涉及很多不确定因素 ,位段是不跨平台的,注重可移植的程序应该避免使用位段【因为C语言也没有给出明确的规定,每个编译器都是按照自己的规定去理解的,所以不支持跨平台】;
我们将上述代码画出内存图,如下所示 ->
1. 所以该 结构体 S 所占用的空间为 8 个字节;
2. 也能够看出在 VS编译器 中使用内存时 -> 从低位向高位依次去使用;
总结一下:
我们的位段就是为了节省内存空间资源而出现的,如果不用位段的话,4 个 int 类型要占用 16 个字节的内存空间,但是用了位段之后只需要 8 个字节的内存空间即可【虽然这 8 个字节中浪费了一小部分的 bit 位空间,但是总体来说是节省了大部分的空间】;
接下里再看看 char 类型的位段是如何存储的 ->
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 = 20;
s.c = 3;
s.d = 4;
return 0;
}
最后去内存中验证的时候存储的内容确实就是 2 2 0 3 0 4 ;
那么就能够证实 char 类型的位段是如下分配空间的 ->
1. 首先将第一次分配的 1字节 分配了 3 bit 给 a;然后由分配了 4 bit 给 b;
2. 给 c 分配 5 bit 的时候发现第一次分配的 1 字节不够用了,所以又重新分配了 1 字节给你,然后再从这 1 字节中分配 5bit 给 c:
3. 最后分配给 d 4bit的时候又发现第二次分配的 1 字节不够用了,同理再次重新分配 1 字节给你,然后再给 d 分配 4 bit 的内存空间;
位段的跨平台问题:
1. int 位段被当成有符号数还是无符号数是不确定的;
2. 位段中最大位的数目不能确定;(16位机器最大16,32位及其最大32,写成27,在16位机器会出问题);
3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义;
4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的;
总结:
跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台问题的存在;