通过这篇博客,你可以知道关于位段的4点:
- 位段是什么,该如何声明
- 位段和结构体的区别
- 位段内存对齐
- 缺点何在(跨平台问题)
1、位段是什么,该如何声明
我们先来写一个位段的声明:
struct A
{
int a:2;//注意,这里有一个冒号,后还接了个数字
int b:4;//另外,位段成员只能是整型家族成员,不可以为浮点数
int c:10;
int d:32;
};
现在我们就创建了一个位段的声明,它的标签是A,里面包含了4个int类型。
我们可以看出来,位段和结构长得非常像,不过就是每个类型后面多了一个冒号和一个数字而已。
这个冒号和数字是什么含义呢?
冒号用来引出这个数字,而数字代表的是这个结构成员所占的内存。
int a:4;
这条代码的含义是:申请2个bit的空间,存放变量a,a的类型是int
2、位段和结构体的区别:
在位段里,我们可以只给int的类型的数据开辟2个比特,甚至可以只给它分配1个比特位,让它只能表示0和1。
但结构不行。在结构中,int类型的数据就是2或4个字节,无法改变。
这就是他们之间的区别,也是我们为什么会创造出位段的原因:它可以有效地节省空间。
我们知道,结构成员为4个int的结构,占用的内存是4*4 == 16个字节(int为4位的机器上)。
3、位段内存对齐
那我们说位段可以节省了空间,现在我们看看A占了多大空间:
sz = sizeof(struct A);//输出8,运行结果见下图
我们可以看出来,确实是比结构小,但为什么是8呢,位段是怎么计算的?
我们现在来解析:
我们存放的是1,2,3,4,为什么系统显示的是C9 和一个4呢?
请看图分解:
位段的对齐规则为:
- 同类型、相邻的,可以放在同一个字节里。
- 不是同类型的、相邻的位段成员,不可以放在同一个字节里。
而它的内存是以数据类型为单位开辟空间的,我们这里是int,所以先开辟一个int的空间(4个字节),当4个字节不够用时,又开辟了一个int,所以用sizeof求出来的字节大小是8
4、位段的缺点
它的缺点主要是跨平台问题。
它的很多东西都是未定义的,
可能你在这个平台或编译器出去用起来是这样,另一个平台或编译器用起来又是另一个样子。
比如:
- 位段中,int被当成有符号数还是无符号数不确定
- 位段中, 最大位的数目不确定。可能16位,也可能32位,这些都没有标准的定义。
- 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。(我们图中的内存分配是从右到左,但换了一个编译器可能是从左到右)
- 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。(我们图中的是直接舍弃,然后在新开辟的空间里存放。但换了一个编译器可能就不一样了)