声明
位段的声明方式与结构体普通成员类似,不过有两点不同:
1.位段的成员必须是 int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字(<类型大小。
在实际工程中有很多变量不需要太大的内存空间。此时我们可以使用位段来减小变量对空间的占用。位段把多个小变量放在一个字节(char)或四个连续字节(int)中。
存放顺序:
内存字节地址从低到高,内存内部的比特编号从低到高。
如:
struct A
{
char a : 3;
char b : 3;
}S1;
int main()
{
S1.a = 5;
S1.b = 4;
printf("%d", *((char*)&S1));
return 0;
}
以上代码的运行结果为37,它的二进制序列为00100101。100是4的二进制,101是五的二进制故可以得出,先创建的成员a被放在了低位,后创建的成员b放在了高位。
无名位段
无名位段的大小是0.。(只有无名位段的大小可以是0),它的作用是迫使下一个成员对齐边界。
如:
#include<stdio.h>
struct A
{
char a : 1;
char b : 1;
};
struct B
{
char a : 1;
char :0;
char b : 1;
};
int main()
{
printf("使用无名位段前结构体大小:%d\n", sizeof(struct A));
printf("使用无名位段后结构体大小:%d\n", sizeof(struct B));
return 0;
}
在以上代码中,不使用无名位段时,a和b在同一个字节内,结构体大小为1。使用无名位段后,b被迫与边界对齐,所以多占了一个字节。
位段的跨平台问题
位段有许多的未定义行为
1. int 位段被当成有符号数还是无符号数是不确定的。
2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,如果写成27,在32位机器上不会出问题,而在16位机器会出问题
3. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。
如:
struct A
{
int a : 30;
int b : 3;
int c : 30;
};
int main()
{
printf("%d", sizeof(A));
return 0;
}
这个代码中前四个字节,a已经占了30位,还剩2位。此时b不够。就可能舍弃剩余的2位。重新占四个字节。接下来剩29位,又不够给c,只能再开辟四个字节。最终结构体大小位为3。
但如果不舍弃前四个字节剩余的2位,那么b只需在接下来的四个字节中占用1位,然后接下来四个字节剩31位,够c用。最终结构体大小为2。
位段是C语言中用于节省内存空间的一种方式,它允许将小变量存储在同一个字节或连续字节中。文章提到了位段的声明规则,例如成员必须是int的变种,并且指定了位数。无名位段用于强制对齐边界。然而,位段存在跨平台的未定义行为,如类型解释和最大位数不确定性,以及在不同情况下的内存布局问题。示例代码展示了位段如何影响结构体大小和内存布局。

360

被折叠的 条评论
为什么被折叠?



