关于结构体的位域(位段)的字节数

 

 

一、位域的大小与对齐

  如果结构体中含有位域(bit-field),那么VC中准则是:

  1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;

  2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;

  3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式(不同位域字段存放在不同的位域类型字节中),Dev-C++和GCC都采取压缩方式;
       4)一个位域必须存储在同一个字节中,不能跨两个成员变量类型。如一个成员变量所剩空间不够存放另一位域时,应从下一成员变量起存放该位域。也可以有意使某位域 从下一成员变量开始。

例如:

typedef struct data{
     int a:5;
     int b:7;
     int c:3;
}DATA1;

 sizeof(DATA1)=4

分析:

int a:5占5比特, int b:5占5比特,int c:3占3比特;

5+5=10 比特 ,小于sizeof(int),即大于4字节(32比特),

同时,

10比特+3比特=13比特,依然小于sizeof(int),即小于4字节,

所以,位域a、位域b、位域c的存储空间大小共占4字节。

所以,sizeof(DATA1)=4字节。

 

typedef struct data{
     int a:29;
     int b:29;
     int c:4;
}DATA2;
sizeof(DATA2)=12。

分析:

int a:29占29比特, int b:29占27比特,int c:4占4比特;

29+29=58 比特 ,大于sizeof(int),即大于4字节(32比特),

所以,

位域a的存储空间大小为4字节;

同时,

29+4=33比特,大于sizeof(int),即大于4字节,所以位域b、位域c的存储空间大小各占4字节。

所以,sizeof(DATA2)=4字节+4字节+4字节=12字节。

 

typedef struct data{
     int a:27;
     int b:27;
     int c:4;
}DATA3;

sizeof(DATA3)=8。
分析:

int a:27占27 bits, int b:27占27 bits,int c:4占4 bits,27+27=54 比特 ,大于sizeof(int),即大于4字节(32比特)

所以,

位域a的存储空间大小为4字节;

但是,

27+4=32比特,等于sizeof(int),即4字节,

所以,

位域b和位域c的存储空间大小为4字节

所以,sizeof(DATA3)=4字节+4字节=8字节。
 

 

 

 

二、位域存放的值

#include<iostream>
using namespace std;
 
struct TEST{
	int a:5;
	int b:7;
	int c:3;
};
 
 
void main()
{
 
	TEST mytest;
	memcpy(&mytest,"HelloWorld",sizeof(mytest));
	cout<<mytest.a<<endl;		
	cout<<mytest.b<<endl;
	cout<<mytest.c<<endl;
}

结果分析:

内存拷贝函数只拷贝了4个字符到mytest中,mytest中的三个变量加起来才15位,其它17位我们不要管。那么这15位中的值是怎么样的呢?15位还没到2个字节,所以这15位中全在He中,H的AscII码为72(01001000),e的AscII 码为112(01100101),根据小端法,我们知道他们的存储方式为:01100101 01001000,a占前5位:01000即8;

b占接下来的7位,0101010即42;c占接下来的3位,110即-2(因为这里是有符号数,高位为1,表示负数,所以是-2)。
 

 

 

#include <iostream>
#include <memory.h>
using namespace std;
struct A
{
    int a:5;
    int b:3;
};
int main(void)
{
    char str[100] = "0134324324afsadfsdlfjlsdjfl";
        struct A d;
    memcpy(&d, str, sizeof(A));
    cout << d.a << endl;
    cout << d.b << endl;
    return 0;
}

$ ./langxun.exe
-16
1

结果分析:

在默认情况下,为了方便对结构体内元素的访问和管理,当结构体内的元素长度都小于处理器的位数的时候,便以结构体里面最长的元素为对其单位,即结构体的长度一定是最长的数据元素的整数倍;如果有结构体内存长度大于处理器位数的元素,那么就以处理器的位数为对齐单元。由于是32位处理器,而且结构体中a和b元素类型均为int(也是4个字节),所以结构体的A占用内存为4个字节。

上例程序中定义了位域结构A,两个个位域为a(占用5位),b(占用3位),所以a和b总共占用了结构A一个字节(低位的一个字节)。

当程序运行到14行时,d内存分配情况:

 高位 00110100 00110011   00110001    00110000 低位
       '4'       '3'       '1'          '0'  
 其中d.a和d.b占用d低位一个字节(00110000),d.a : 10000, d.b : 001

 d.a内存中二进制表示为10000,由于d.a为有符号的整型变量,输出时要对符号位进行扩展,所以结果为-16(二进制为11111111111111111111111111110000)

 d.b内存中二进制表示为001,由于d.b为有符号的整型变量,输出时要对符号位进行扩展,所以结果为1(二进制为00000000000000000000000000000001)

 

 

参考链接:

https://blog.csdn.net/mydreamremindme/article/details/10285533

https://www.cnblogs.com/bigrabbit/archive/2012/09/20/2695543.html

https://www.cnblogs.com/x_wukong/p/5743369.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值