位域(struct中的冒号)、#pragma pack、sizeof等等若干

1.位域(struct中的冒号)

struct中的冒号表示强行为某变量指定存储空间大小。例如:

typedef struct {
	int a:1;
	int b:2;
	int c:5;
} AA;
在这个结构体之中,a只占1个bit空间,b占2个bit空间,c占5个bit空间。

因此,整个AA只占8个bit空间,即只占一个字节。

另外说明一点,即在一个byte之内a,b,c是从低向高取值的。

例如AA x;,其中x处地址存放的数据为10101010;

那么从右往左看,x.a将为0,x.b将为二进制的01,x.c将为二进制的10101。


那么输出sizeof(AA),得到的结果是否为1呢?另我大吃一惊的是,实际结果是4。

我们可以看到,如果不加冒号,这个结果应该是12,这说明我们添加的冒号还是有效的。那为什么输出结果是4呢?


2.#pragma pack(n)

这涉及到内存对齐的问题了。编译器为了方便CPU进行取址操作,会对struct中的数据分配空间时自动对齐。默认的对齐的字节数可以为1、2、4、8、16。

我们可以通过宏指令#pragma pack(n)来强行转换对齐的字节数大小。

例如:

typedef struct {
	char a;
	int b;
} AA;
因为内存对齐的原因,这个结构体所占空间为8。但是我们更改一下对齐方式,在最前面加入#pragma pack(2),
#pragma pack(2)
typedef struct {
	char a;
	int b;
} AA;
我们会发现sizeof(AA)现在的大小为6!这便是#pragma pack(n)的作用。

另外提醒一下,这里头的n必须为1、2、4、8、16才有效。另外,编译器将会在struct中空间最大的变量所占字节数与自定义的n之间取最小值来完成对齐。例如:

#pragma pack(8)
typedef struct {
	short a;
	short b;
} AA;
你认为输出将会为8?错了,输出为4,因为默认为2字节对齐,小于自定义的8。

还可以保存和恢复目前的对齐方式,语句分别是

#pragma pack(push)
#pragma pack(pop)


回到原来的问题上,sizeof(AA)输出为4就是因为对齐的原因。编译器检测到int参数的存在,因此将会默认4字节对齐。即使只占用了一个字节的空间,sizeof(AA)也将会输出4。

我们在最开始强制转换为1字节对齐,如下:

#pragma pack(1)
typedef struct {
	int a:1;
	int b:2;
	int c:5;
} AA;
现在的sizeof(AA)就会输出1了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值