位域对齐问题

在编写一个C++小程序时,遇到了与位域相关的问题,为此查看相关资料并通过试验进行验证。


首先,查看C++Primer中的相关介绍,主要内容如下:

1. 位域在内存中的布局是机器相关的;

2. 位域必须是整型数据类型,可以是signed或unsigned;

3. 地址操作符(&)不能用于位域。


试验验证:

1. 位域的对齐及长度问题(暂时只考虑将结构体对齐方式设置为1字节的情况)

考虑下面的三种位域定义,其长度分别是多少?

struct BF1{
    char s1: 6;
    char s2: 3;
    char s3: 6;
    char s4: 3;
    char s5: 6;
    char s6: 3;
};

struct BF2{
    char16_t s1: 6;
    char16_t s2: 3;
    char16_t s3: 6;
    char16_t s4: 3;
    char16_t s5: 6;
    char16_t s6: 3;
};

struct BF3{
    char32_t s1: 6;
    char32_t s2: 3;
    char32_t s3: 6;
    char32_t s4: 3;
    char32_t s5: 6;
    char32_t s6: 3;
};

答案是:





下面分析造成长度不同的原因,查看3个位域类型中,各位段的对齐方式。

分别定义3种类型的变量,并将其中3bit宽度的位段各位全置为1:

    struct BF1 bf1;
    struct BF2 bf2;
    struct BF3 bf3;

    memset(((unsigned char*)&bf1),0,sizeof(BF1));
    memset(((unsigned char*)&bf2),0,sizeof(BF2));
    memset(((unsigned char*)&bf3),0,sizeof(BF3));
    bf1.s1 = bf2.s1 = bf3.s1 = 0;
    bf1.s2 = bf2.s2 = bf3.s2 = 7;
    bf1.s3 = bf2.s3 = bf3.s3 = 0;
    bf1.s4 = bf2.s4 = bf3.s4 = 7;
    bf1.s5 = bf2.s5 = bf3.s5 = 0;
    bf1.s6 = bf2.s6 = bf3.s6 = 7;

然后分别输出bf1、bf2、bf3的二进制数据内容:



可以看出,使用不同的数据类型来定义位域中各个位段,其内部各位段的分布是不同的。

使用char型定义(8位对齐):


使用char16_t型定义(16位对齐):


使用char32_t型定义(32位对齐):



在bf1中,使用char类型定义位域的各个位段时,将以char类型的长度(8bit)来分配空间,首先为s1分配6bit,然后分配s2的3bit时,已经超出了8bit,在一个char型长度中放不下,因此位段s2被分配到下一个char长度单元中;同理分配s3时,也无法与s2分配到同一个char长度单元中,于是分配到第3个char长度单元中。

同理,在bf2、bf3中,将分别以16位、32位为长度单位来分配各个位段,于是在同一个长度单位中能分配下的位段也不同,就造成了存放各位段位置的不同。


最后,再看下《C++编程金典》中对使用位域的提醒:


  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值