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
原则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
相关文章推荐