结构体对齐(字节计算,包括位结构体)

结构体对齐规则: 
(1)每个成员分别按自己的对齐字节数和指定对齐字节数(Linux 64位默认为8)小的那个对齐,这样可以最小化长度。如在32bit的机器上,int的大小为4,因此int存储的位置都是4的整数倍的位置开始存储。 
(2)复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,结构体数组的时候,可以最小化长度。
(3)结构体对齐后的长度必须是成员中最大的对齐参数(PPB)的整数倍,这样在处理数组时可以保证每一项都边界对齐。 
(4)结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储。如 struct A 中包含 struct B, struct B 中包含数据成员 char, int, double,则 struct B 应该以sizeof(double)=8的整数倍为起始地址。

#pragma pack(2)    指定 2 字节对齐(对齐系数2);

#pragma pack(1)    指定 1 字节对齐(对齐系数1);

#include"common.h"
//环境为ubuntu 16.04 64位
//p[]代表内存地址

struct A0{
    char a;   //p[0]
    char b;   //p[1]
    char c;   //p[2]
};
//默认每个变量以(1<4) 1进行对齐,所以长度为 1 + 1 + 1 = 3


struct A1{
    char a;     //p[0]
    int b;      //p[4]  4对齐,所以向右偏移3个单位开始存储
    long int c; //pp[8] 4对齐,8是4的倍数,不用偏移
    char d;     //p[16]
};
//每个变量根据自己的类型与指定对齐字节数进行对比,取较小的对齐
//结构体长度为 (1+3) + 4 + 8 + (1+3) + [4]  = 24 ------规则3,所以补充4个字节


struct A2{
	char a;     //p[0]
	int b;      //p[4]  4对齐,所以向右偏移3个单位开始存储
    char c;     //[8]
    long int d; //pp[16] 8对齐,向右偏移7个单位开始存储
    char e;     //p[24]
};
//每个变量根据自己的类型与指定对齐字节数进行对比,取较小的对齐
//结构体长度为 (1+3) + 4 + (1+7) + 8 + 1 + [7] = 32 


#pragma pack(4)
struct A3{
	char a;     //p[0]
	int b;      //p[4]
    char c;     //[8]
    long int d; //pp[12] 4对齐,12就可以,不必要再偏移至16
    char e;     //p[20]
};
#pragma pack()
//指定对齐系数为4
//结构体长度为 (1+3) + 4 + (1+3) + 8 + 1 + [3] = 24


//--------------------------------------------------//


struct B0{

     char a;      //p[0]
     int b;       //p[4]
     short c;     //p[8]
     char d;      //p[10]
     int f;       //p[12]
     long int e;  //p[16]
   
};
//对齐系数默认为8
//结构体长度为 (1+3) + 4 + 2 + (1+1) + 4 + 8  = 24


struct B1{

     char a;       // p[0]
     long int b;   //p[8]
     short c;      // p[16]
     struct B0 d;  //p[24] //最大数据成员为8,所以要以24开始存储
   
};
//对齐系数默认为8
//结构体长度为 (1+7) + 8 + (2+6) + 24  = 48 


#pragma pack(1)
struct B2{

     char a;      //p[0]
     int b;       //p[1]
     short c;     //p[5]
     char d;      //p[7]
     int f;       //p[8]
     int e;  	  //p[12]
   
};
#pragma pack()
//对齐系数为1
//结构体长度为 1 + 4 + 2 + 1 + 4 + 4 = 16

struct B3{

     char a;       //p[0]
     int b;        //p[4]
     short c;      //p[8]
     struct B2 d;  //p[12] //最大数据成员为4,所以要以12开始存储
   
};
//对齐系数默认为8
//结构体长度为 (1+3) + 4 + (2+2) + 16  = 28 


//-------------------------------------------------//



struct C0{

	unsigned a : 1;  //会紧凑的以4字节分配内存

};
//结构体长度为 4


struct C1{

	int a : 1;  //会紧凑的以4字节分配内存

};
//结构体长度为 4

struct C2{

	char a : 1;  //会紧凑的以1字节分配内存

};
//结构体长度为 1

struct C3{

	char a : 1;  //会紧凑的以1字节分配内存
	char b : 2;
	char c : 3 ;
};
//1字节够用,所以长度为1

struct C4{

	char a : 1;  
	char b : 2;
	int c : 1 ; //会紧凑的以4字节分配内存
};
//长度为4

struct C5{

	char a : 1;  
	char b : 2;
	int  c : 31;
	int  d : 20; //会紧凑的以4字节分配内存
};
//长度为 4(a&b) + 4(c) + 4(d) =12  

struct C6{

	unsigned a : 1;  
	long	 b : 32;  //会紧凑的以8字节分配内存
	int		 c : 15;  
	unsigned d : 20;  
	unsigned e : 30;  
	unsigned f : 20;  
	char g;

};
//结构体长度为 8(a&b&c) + 8(d&e) + 8(f&g) = 24


int main()
{
//分析位结构体的内存分配(普通结构体可直接打印地址)
	struct C6 my;
    memset((char*)&my,0,sizeof(struct C6));//一定要清空,否则间隙的内存可能会有乱的数据影响分析
	my.a = 1;
	my.b = 2;
	my.c = 3;
	my.d = 4;
	my.e = 5;
	my.f = 6;
	my.g = 7;
	int fp = open("test.bin",O_RDWR | O_CREAT,0666);
	write(fp,(char*)(&my),sizeof(struct C6));
	close(fp);
//
	printf("A0== %ld\n",sizeof(struct A0 ));
    printf("A1== %ld\n",sizeof(struct A1 ));
    printf("A2== %ld\n",sizeof(struct A2 ));
	printf("A3== %ld\n",sizeof(struct A3 ));
    printf("B0== %ld\n",sizeof(struct B0 ));
    printf("B1== %ld\n",sizeof(struct B1 ));
	printf("B2== %ld\n",sizeof(struct B2 ));
	printf("B3== %ld\n",sizeof(struct B3 ));
    printf("C0== %ld\n",sizeof(struct C0 ));
	printf("C1== %ld\n",sizeof(struct C1 ));
	printf("C2== %ld\n",sizeof(struct C2 ));
	printf("C3== %ld\n",sizeof(struct C3 ));
	printf("C4== %ld\n",sizeof(struct C4 ));
	printf("C5== %ld\n",sizeof(struct C5 ));
	printf("C6== %ld\n",sizeof(struct C6 ));

   
}

用UE软件打开所存的文件内容为:

经过大小端处理之后:

把开始的8个字节进行分析,先转换为二进制:

可以发现,在C6结构体中,a占了1位,b占了32位,c占了15位,剩余的64-1-32-15间隙

 

中间8个字节:

d和e每个分了32位,暂时不清楚原因。

末尾8个字节:

f分了24位,其它的分给g以及空隙

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值