您的位置:首页 > 其它

C 结构体字节对齐规则

2018-01-29 11:10 357 查看
文档下载:结构体字节对齐规则

原则1:数据成员的对齐规则(以最大的类型字节为单位)。

结构体(struct)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存放在offset为该数据成员大小的整数倍的地方(比如int在32位机为4字节,则要从4的整数倍地址开始存储)

 

原则2:结构体作为成员的对齐规则。

如果一个结构体B里嵌套另一个结构体A,则结构体A应从offset为A内部最大成员的整数倍的地方开始存储。(struct B里存有struct A,A里有char,int,double等成员,那A应该从8的整数倍开始存储。),结构体A中的成员的对齐规则仍满足原则1、原则2。

注意:

1. 结构体A所占的大小为该结构体成员内部最大元素的整数倍,不足补齐。

2. 不是直接将结构体A的成员直接移动到结构体B中

 

原则3:收尾工作

结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。

///////////////////1

struct

{

       int a;

       short b;

}A;

//对齐单位为 4 个字节

//偏移量:

a: 4*0 = 0

b: 2*2 = 4 



sizeof(A) = 8;

/////////////////////2

struct

{

       int a;

       char b;

       short c;

}A;

//对齐单位 4 个字节

sizeof(A) = 8;

a: 4*0 = 0

b: 1*4 = 4

c: 2*3 = 6



 

/////////////////////3

struct

{

       char b;

       int a;

       short c;

}A;

sizeof(A) = 12;

b: 1*0 = 0

a: 4*1 = 4

c: 2*4 = 8



/////////////////////4

struct A

{

       int a;

       doubleb;

       float c;

};

 

struct

{

       chare[2];

       int f;

       doubleg;

       short h;

       struct Ai;

}B;

//对齐单位 8 个字节

sizeof(B) = 48;

//普通成员偏移量

e: 1*0 = 0

f: 4*1 = 4

g: 8*1 = 8

h: 2*8 = 16

结构体起点坐标:

   8*3 = 24

//结构体成员偏移量

a: 24 + 4*0 = 24

b: 24 + 8*1 = 32

c: 24 + 4*4 = 40



/////////////////////6

struct A

{

       int a;

       doubleb;

       float c;

};

 

struct

{

       chare[2];

       int f;

       Int g;

       short h;

       struct Ai;

}B;

//对齐单位 8 个字节

sizeof(B) = 40

//普通成员偏移量

e: 2*0 = 0

f: 4*1 = 4

g: 4*2 = 8

h: 2*6 = 12

结构体起点坐标:

   8*2 = 16

//结构体成员偏移量

a: 16 + 4*0 = 16

b: 16 + 8*1 = 24

c: 16 + 4*4 = 32



/////////////////////6

struct A

{

       char e;

       short f;

};

 

struct

{

       int a;

       char b;

       struct Ac;

       char d;

}B;

sizeof(B) = 12;

a: 4*0 = 0;

b: 1*4 = 4;

结构体起点坐标:

       2*3 = 6

e: 6+1*0 = 6

f: 6+2*1 = 8

d: 1*10 = 10



/////////////////////7

struct A

{

       int e;

       short f;

};

 

struct

{

       int a;

       char b;

       struct Ac;

       short d;

}B;

sizeof(B) = 20;

a: 4*0 = 0

b: 1*4 = 4

结构体起点:

       4*2 = 8

e: 8 + 4*0 = 8

f: 8 + 2*2 = 12 //结构体A所占的大小为该结构体成员内部最大元素的整数倍,不足补齐。

d: 2*8 = 16



/////////////////////8

#pragma pack(2) //指定对齐单位为2个字节

typedef struct

{

       int a;

       char b;

       short c;

       char d;

}A;

a: 2*0 = 0

b: 1*4 = 4

c: 2*3 = 6

d: 1*8 = 8

sizeof(A) = 10;



#pragma pack(2)

typedef struct

{

       char a;

       char b;

       short c;

       int d;

}A;

a: 1*0 = 0

b: 1*1 = 1

c: 2*1 = 2

d: 2*2 = 4

sizeof(A) = 8;



#pragma pack(1)

typedef struct

{

       int d;

       char a;

       short c;

       char b;

}A;

sizeof(A) = 8

 

//////////////////有关不完整类型的字节对齐

使用位域的主要目的是压缩存储,其大致规则为:

1) 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。

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

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

4) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++和gcc采取压缩方式;

5) 如果位域字段之间穿插着非位域字段,则不进行压缩;

6) 整个结构体的总大小为最宽基本类型成员大小的整数倍。

//以 4 字节对齐

struct A

{

    int     a1:5;

    int     a2:9;

    char    c;

    int     b:4;

    short   s;

}B;

 

sizeof(B) = 16

 

a1 + a2 = 14 位,少于32位,4字节

a1+a2存放在一起:4*0 = 0

c: 1 * 4 = 4

b: 4 * 2 = 8 //所占的大小为该结构体成员内部最大元素的整数倍(4对齐),不足补齐。

s: 2 * 6 = 12 



#pragma pack(2)    //2字节对齐

struct A

{

       int     a1 : 5;

       int     a2 : 9;

       char    c;

       int     b : 4;

       short   s;

}B;

sizeof(B) = 12;

 

a1+a2 = 14 (小于32位,4字节)

a1+a2: 2 * 0 =0;

c: 1 * 4 = 4;

b:  2 * 3 =6;  //4超过2字节,以2字节为单位

s:2 * 5 = 10



struct  A

{

       int   a : 5;

       int   b : 7;

       int   c : 6;

       int   d : 9;

       char  e : 2;

       int   x;

}B;

sizeof(B) = 12

a+b+c+d = 27 < 32

a+b+c+d放在一起: 4 * 0 = 0

e : 1 * 4 = 4

x:   4 * 2 = 8



 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: