(C语言)结构体内存对齐
目录
1.对齐规则
2.示例
例1
例2
例3
3.存在内存对齐的原因
1.平台原因
2.性能原因
4.修改默认对齐数
1.对齐规则
(1)结构体的第一个成员放在偏移量(相较于结构体变量的起始位置)为0的位置
(2)从第二个成员起,之后的每个成员都要对齐到对齐数的整数倍的地址处
对齐数:编译器默认的对齐数与该成员大小的较小值
VS中默认为8
Linux中无默认对齐数,对齐数就是成员自身大小
(3)结构体总大小为最大对齐数(所有成员对齐数的最大值)的整数倍
(4)如果出现嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍
(5)当出现数组,数组的对齐数为数组元素与默认对齐数的较小值
2.示例
(以下均在VS下实现)
例1
#include <stdio.h>
struct s1
{
char c1;
int i;
char c2;
};
int main()
{
printf("%d", sizeof(struct s1));//12
return 0;
}
计算结果为12,我们结合内存分布图来计算
c1为char类型,占1个字节,第一个成员放在偏移量为0的位置,(char的对齐数为1)
i为int类型,占4个字节,因此从偏移量为4的位置开始存放
c2为char类型,占1个字节,1为c2的默认对齐数,因此在i的后面接着存放c2,放在偏移量为9的位置处
结构体的最大对齐数为4,结构体的总大小为最大对齐数的整数倍,此时已经使用了9个字节的空间,则结构体的大小为12
例2
#include <stdio.h>
struct s1
{
char c1;
int i;
char c2;
};
struct s2
{
char c;
struct s1 s;
int i;
};
int main()
{
printf("%d\n", sizeof(struct s1));//12
printf("%d\n", sizeof(struct s2));//20
return 0;
}
计算结果为20
c为char类型,占1个字节,第一个成员放在偏移量为0的位置,(char的对齐数为1)
由例1计算得出s的大小为12,s为结构体类型,对齐到自己的最大对齐数的整数倍处,s中的3个成员分别为char、int、char类型,最大对齐数为4,因此s对齐到偏移量为4的地址空间处。
i为int类型,对齐数为4,因此对齐到偏移量为16的地址空间处。
此时已经使用20个字节的空间,结构体的最大对齐数为4,因此结构体的大小为20
例3
#include <stdio.h>
struct s3
{
char c1;
int arr[2];
char c2;
};
int main()
{
printf("%d\n", sizeof(struct s3));//16
return 0;
}
c1为char类型,占1个字节,第一个成员放在偏移量为0的位置,(char的对齐数为1)
arr[2]为数组,当出现数组时,对齐数为元素大小与默认对齐数的最小值,arr[2]的元素为int类型,对齐数为4,因此对齐到偏移量为4的地址空间处
c2为char类型,占1个字节,1为c2的默认对齐数,因此在arr[2]的后面接着存放c2,放在偏移量为12的位置处
3.存在内存对齐的原因
1.平台原因
并不是所有的硬件平台都可以访问任意地址上的任意数据。某些硬件平台只能在某些地址处取得某些特定类型的数据,否则会抛出硬件异常。
2.性能原因
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因:为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问
可以说,结构体的内存对齐是拿空间换时间
当在使用结构体时,为了满足对齐,同时节省空间,可将占用空间小的成员尽量集中在一起
4.修改默认对齐数
结构在对齐方式不合适时,可以自己修改默认对齐数
使用#pragma预处理指令,可以修改默认对齐数(通常设置为2的次方数)
#include <stdio.h>
#pragma pack(4)//设置默认对齐数为4
struct s1
{
// 成员大小 默认对齐数 对齐数
char c;// 1 4 1
double d;//8 4 4
int i;// 4 4 4
};
#pragma pack()//取消设置的默认对齐数,还原为默认对齐数
struct s2
{
// 成员大小 默认对齐数 对齐数
char c;// 1 8 1
double d;//8 8 8
int i;// 4 8 4
};
int main()
{
printf("%d %d", sizeof(struct s1),sizeof(struct s2));
return 0;
}
struct s1
struct s2
还没有评论,来说两句吧...