结构体的内存对齐问题
标签(空格分隔): 结构体内存对齐
一、对齐方式
1、从偏移为0的位置开始存储;
2、如果没有定义 #pragma pack(n)
sizeof 的最终结果必然是结构内部最⼤成员的整数倍,不够补⻬;
结构内部各个成员的⾸地址必然是⾃身⼤⼩的整数倍;
3、如果定义了 #pragma pack(n)
sizeof 的最终结果必然必然是 min[n,结构内部最⼤成员] 的整数倍,不够补⻬;
结构内部各个成员的⾸地址必然是 min[n,⾃身⼤⼩] 的整数倍。
二、#pragma pack(n)
它是一个用于控制结构体成员对齐的指令,编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。摘自 作者 。
三、实例
1、没加#pragma pack(n)
#include <stdio.h>
#include <Windows.h>
using namespace std;
/**************************************************************
* 结构体内存对⻬问题
* 从偏移为0的位置开始存储;
* 如果没有定义 #pragma pack(n)
* sizeof 的最终结果必然是结构内部最⼤成员的整数倍,不够补⻬;
* 结构内部各个成员的⾸地址必然是⾃身⼤⼩的整数倍;
*
***************************************************************/
struct S1
{
int i ; //起始偏移0,sizeof(i)=4; 地址0、1、2、3分配给成员i
char j ; //起始偏移4,sizeof(j)=1;
int a ; //sizeof(a)=4,内存对齐到8个字节,从偏移量为8处存放a;
double b;//sizeof(b)=8,内存对齐到16个字节,再存放b,结构体总大小24;
};
//结构体成员的首地址必须是自身大小的整数倍
struct S3
{
char j;//起始偏移0,sizeof(j)=1;
float i;//sizeof(i)=4,内存对齐到4,起始偏移量为4,再存放i
double b;//当前地址为8,是b大小的整数倍,无需对齐,直接存放成员b 8个字节
int a;//sizeof(a)=4,内存对齐到20,再存放a,总大小24字节;
};
int main()
{
printf("%d\n", sizeof(S1));
printf("%d\n", sizeof(S3));
system("pause");
return 0;
}
输出结果:
2、添加#pragma pack(n)
#include <stdio.h>
#include <Windows.h>
using namespace std;
#pragma pack(4)
/**************************************************************
* 结构体内存对⻬问题
* 从偏移为0的位置开始存储;
* 如果定义了 #pragma pack(n)
* sizeof 的最终结果必然必然是 min[n,结构内部最⼤成员] 的整数倍,不够补⻬;
* 结构内部各个成员的⾸地址必然是 min[n,⾃身⼤⼩] 的整数倍。
*
***************************************************************/
struct S1
{
int i ; //起始偏移0,sizeof(i)=4;
char j ; //起始偏移4,sizeof(j)=1;
int a ; //sizeof(a)=4,内存对齐到8,再存放a;
double b;//sizeof(b)=8,min[4,8]=4,当前地址12,无需进行内存对齐,直接存放b,结构体总大小20;
};
struct S3
{
char j;//起始偏移0,sizeof(j)=1;
float i;//sizeof(i)=4,内存对齐到4,起始地址为5,再存放i
double b;//当前地址为8,min[8,4]=4,,无需对齐,直接存放成员b 8个字节
int a;//sizeof(a)=4,当前地址16,为a大小的整数倍,无需对齐,总大小20字节;
};
int main()
{
printf("%d\n", sizeof(S1));
printf("%d\n", sizeof(S3));
system("pause");
return 0;
}
输出结果: