C-结构体对齐
2016-09-23 19:28
169 查看
技术群的筒子们有时候会提到结构体对齐,说实话这个问题还不是几句话能讲清楚的。这个问题网上一搜一大把,已经有无数的前辈总结过。看了很多网上的资料,根据我个人的一些理解,再总结一下,配了些图片,希望大家能看懂。
首先是结构体对齐规则:
1、对于n个字节的元素,它的首地址要能被n整除
eg:int—4个字节的元素,它为结构体的第一个元素时,起始地址应能被4整除
double—8个字节的元素,它为结构体的第一个元素时,起始地址应能被8整除
2、结构体成员在内存中顺序存放,所占内存地址依次增高,第一个成员处在低地址处,最后一个成员处在高地址处,但结构体成员之间的内存分配不一定是连续的
3、对待每个成员,类似于对待单个n字节元素一样,依次为每个元素找一个合适的首地址,使其符合第一条对齐原则
4、编译器可设置对齐参数X,但这个X并不是结构体成员的实际对齐参数,结构体中每个成员的对齐参数N这样计算
N= min(sizeof(成员类型),X)
5、整个结构体的长度必须是各成员所使用的对齐参数N中最大的那个值的整数倍
即总长度LEN= {max(N1,N2,……,N)}的最小整数倍
6、当结构体成为为数组时,将数组的每个元素当一个成员来看待
7、当结构体成为类结构类型时,那么该过程是个递归过程,且把该成员当成一个整体来看待
上面的规则有点晕,对照着看下面的例子
#pragma pack(8) //设置编译器以8字节对齐
struct A
{
char c;
//①成员的对齐参数N1= min(sizeof(char) , 8) = 1
double d;
//②成员的对齐参数N2 = min(sizeof(double) , 8) = 8
short s;
//③成员的对齐参数N3 = min(sizeof(short) , 8) = 2
int i;
//④成员的对齐参数N4 = min(sizeof(int) , 8)
= 4
}
结构体的总成都LEN = {max(N1,N2,N3,N4)}的整数倍 ,所以长度LEN必须是8的整数倍,从下面的内存分布图中可看出,总长度是24字节
#pragma pack(4) //设置编译器以4字节对齐
struct A
{
char c;
//①成员的对齐参数N1= min(sizeof(char) , 4) = 1
double d;
//②成员的对齐参数N2 = min(sizeof(double) , 4) = 4
short s;
//③成员的对齐参数N3 = min(sizeof(short) , 4) = 2
int i;
/④成员的对齐参数N4 = min(sizeof(int) , 4)
= 4
}
结构体的总成都LEN = {max(N1,N2,N3,N4)}的整数倍 ,所以长度LEN必须是4的整数倍,从下面的内存分布图中可看出,总长度是20字节
#pragma pack(2) //设置编译器以2字节对齐
struct A
{
char c;
//①成员的对齐参数N1= min(sizeof(char) , 2) = 1
double d;
//②成员的对齐参数N2 = min(sizeof(double) , 2) = 2
short s;
//③成员的对齐参数N3 = min(sizeof(short) , 2) = 2
int i;
//④成员的对齐参数N4 = min(sizeof(int) , 2)
= 2
}
结构体的总成都LEN = {max(N1,N2,N3,N4)}的整数倍 ,所以长度LEN必须是2的整数倍,从下面的内存分布图中可看出,总长度是16字节
#pragma pack(1) //设置编译器以1字节对齐
struct A
{
char c;
//①成员的对齐参数N1= min(sizeof(char) , 1) = 1
double d;
//②成员的对齐参数N2 = min(sizeof(double) , 1) = 1
short s;
//③成员的对齐参数N3 = min(sizeof(short) , 1) = 1
int i;
//④成员的对齐参数N4 = min(sizeof(int) , 1)
= 1
}
这个就不多说了,结构体总长15字节
以上的例子都是在32位的系统上试的,这里两个结构体成员之间的“空隙”我用“cc”来填充,这纯粹是画起来方便,VS2010中这些“空隙”里的值都是0。
当然我之前在单步执行别的C程序的时候发现,很多初始化的内存、栈空间,都以"cc"字符来填充。最近在一本书上看到了解释,抄录在此:
对于X86处理器来说,0xcc是不错的填充数值,因为它是断点中断(int 03h)的机器码,如果你在调试器中运行程序并试图执行一段数据而不是执行代码时,就会陷入断点。
另外,使用0xcc的另一个好处是它可以很容易从内存转储的信息中识别出来
首先是结构体对齐规则:
1、对于n个字节的元素,它的首地址要能被n整除
eg:int—4个字节的元素,它为结构体的第一个元素时,起始地址应能被4整除
double—8个字节的元素,它为结构体的第一个元素时,起始地址应能被8整除
2、结构体成员在内存中顺序存放,所占内存地址依次增高,第一个成员处在低地址处,最后一个成员处在高地址处,但结构体成员之间的内存分配不一定是连续的
3、对待每个成员,类似于对待单个n字节元素一样,依次为每个元素找一个合适的首地址,使其符合第一条对齐原则
4、编译器可设置对齐参数X,但这个X并不是结构体成员的实际对齐参数,结构体中每个成员的对齐参数N这样计算
N= min(sizeof(成员类型),X)
5、整个结构体的长度必须是各成员所使用的对齐参数N中最大的那个值的整数倍
即总长度LEN= {max(N1,N2,……,N)}的最小整数倍
6、当结构体成为为数组时,将数组的每个元素当一个成员来看待
7、当结构体成为类结构类型时,那么该过程是个递归过程,且把该成员当成一个整体来看待
上面的规则有点晕,对照着看下面的例子
#pragma pack(8) //设置编译器以8字节对齐
struct A
{
char c;
//①成员的对齐参数N1= min(sizeof(char) , 8) = 1
double d;
//②成员的对齐参数N2 = min(sizeof(double) , 8) = 8
short s;
//③成员的对齐参数N3 = min(sizeof(short) , 8) = 2
int i;
//④成员的对齐参数N4 = min(sizeof(int) , 8)
= 4
}
结构体的总成都LEN = {max(N1,N2,N3,N4)}的整数倍 ,所以长度LEN必须是8的整数倍,从下面的内存分布图中可看出,总长度是24字节
#pragma pack(4) //设置编译器以4字节对齐
struct A
{
char c;
//①成员的对齐参数N1= min(sizeof(char) , 4) = 1
double d;
//②成员的对齐参数N2 = min(sizeof(double) , 4) = 4
short s;
//③成员的对齐参数N3 = min(sizeof(short) , 4) = 2
int i;
/④成员的对齐参数N4 = min(sizeof(int) , 4)
= 4
}
结构体的总成都LEN = {max(N1,N2,N3,N4)}的整数倍 ,所以长度LEN必须是4的整数倍,从下面的内存分布图中可看出,总长度是20字节
#pragma pack(2) //设置编译器以2字节对齐
struct A
{
char c;
//①成员的对齐参数N1= min(sizeof(char) , 2) = 1
double d;
//②成员的对齐参数N2 = min(sizeof(double) , 2) = 2
short s;
//③成员的对齐参数N3 = min(sizeof(short) , 2) = 2
int i;
//④成员的对齐参数N4 = min(sizeof(int) , 2)
= 2
}
结构体的总成都LEN = {max(N1,N2,N3,N4)}的整数倍 ,所以长度LEN必须是2的整数倍,从下面的内存分布图中可看出,总长度是16字节
#pragma pack(1) //设置编译器以1字节对齐
struct A
{
char c;
//①成员的对齐参数N1= min(sizeof(char) , 1) = 1
double d;
//②成员的对齐参数N2 = min(sizeof(double) , 1) = 1
short s;
//③成员的对齐参数N3 = min(sizeof(short) , 1) = 1
int i;
//④成员的对齐参数N4 = min(sizeof(int) , 1)
= 1
}
这个就不多说了,结构体总长15字节
以上的例子都是在32位的系统上试的,这里两个结构体成员之间的“空隙”我用“cc”来填充,这纯粹是画起来方便,VS2010中这些“空隙”里的值都是0。
当然我之前在单步执行别的C程序的时候发现,很多初始化的内存、栈空间,都以"cc"字符来填充。最近在一本书上看到了解释,抄录在此:
对于X86处理器来说,0xcc是不错的填充数值,因为它是断点中断(int 03h)的机器码,如果你在调试器中运行程序并试图执行一段数据而不是执行代码时,就会陷入断点。
另外,使用0xcc的另一个好处是它可以很容易从内存转储的信息中识别出来
相关文章推荐
- C语言 结构体的内存对齐问题与位域
- 结构体补齐与对齐
- sizeof(结构体)和内存对齐---简洁版
- 结构体struct的成员变量字节对齐问题详解
- 结构体内存对齐
- 结构体对齐
- 结构体对齐
- 结构体字节对齐
- 结构体获取成员偏移值、结构体内存中字节对齐问题
- C/C++中的结构体对齐问题(内存对齐)
- 关于结构体字对齐—BMP文件图像处理程序
- 结构体中的字节对齐问题
- 位域结构体的字节对齐
- C/C++中的结构体对齐问题(内存对齐)
- 结构体和联合体的大小,结构体内存对齐的原因、规则以及柔性数组
- 结构体字节对齐 windows下
- 结构体对齐
- 结构体对齐的具体含义(#pragma pack)
- 结构体字节对齐和位域对齐——VC、gcc
- 关于结构体内存对齐