目录
前言: 为什么存在内存对齐
1.平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
总体来说:结构体的内存对齐是拿取空间换取时间的做法 。
提示:以下是本篇文章正文内容,下面案例可供参考
一、掌握结构体的对齐规则
- 第一个结构体成员在与结构体变量偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。(vs中默认对齐数为8)
-
结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
-
如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
二、如何计算结构体大小
实例解析:
1.计算下列结构体的大小
int main() {
struct s1
{
char c1;
char c2;
int i;
};
struct s2
{
char c1;
int i;
char c2;
};
printf("%d", sizeof(struct s1));
printf("%d", sizeof(struct s2));
return 0;
}
(在vs平台下进行测试)算出s1的大小为8个字节,而s2的大小为12个字节。这是为什么呢?
解析如下:
char l类型的对齐数为1,vs默认的对齐数为8,因此采用较小的1即可;
int 类型的对齐数为4,4也小于8,采用较小的4;
结构体总大小为最大对齐数(每个成员变量都有一个对齐数 ,此时最大对齐数为成员变量 int ,对齐数为4)的整数倍。
对结构体S1的分析 :
对结构体S2的分析:
struct S3
{
int i;
char c1;
long l;
};
printf("%d\n", sizeof(struct S3));
算出的结果为16个字节
char l类型的对齐数为1,vs默认的对齐数为8,因此采用较小的1即可;
int 类型的对齐数为4,4也小于8,采用较小的4;
long 类型的对齐数为8,8=8,采用8。
结构体总大小为最大对齐数(每个成员变量都有一个对齐数 ,此时最大对齐数为成员变量 int ,对齐数为8)的整数倍。
三.进阶
#pragma pack(2)//设置默认对齐数为2
这是修改默认对齐数的操作,我们将默认对齐数改为2,情况如何呢?
#pragma pack(2)//设置默认对齐数为2
struct S4
{
char c1;
int i;
char c2;
};
printf("%d\n", sizeof(struct S4));
得出的结果为8
char 类型的对齐数为1,vs默认的对齐数为2,因此采用较小的1即可;
int 类型的对齐数为4,4大于2,采用较小的2;
结构体总大小为最大对齐数(每个成员变量都有一个对齐数 ,此时最大对齐数为成员变量 int ,对齐数为4)的整数倍。