位段(无名位段与存放顺序的讨论

位段是C语言中用于节省内存空间的一种方式,它允许将小变量存储在同一个字节或连续字节中。文章提到了位段的声明规则,例如成员必须是int的变种,并且指定了位数。无名位段用于强制对齐边界。然而,位段存在跨平台的未定义行为,如类型解释和最大位数不确定性,以及在不同情况下的内存布局问题。示例代码展示了位段如何影响结构体大小和内存布局。

声明

位段的声明方式与结构体普通成员类似,不过有两点不同:

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。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值