struct结构体内存对齐详解
一,什么是内存对齐
1. 即在 计算 一个 结构体对象的 大小的时候 ,其内部成员 占用大小 比 原本类型所占用 的 空间要大 --- 会按照额外的 内存对齐 规则 多占用空间 。
2.现象:
如下图:A 的 成员 一个字符型 (1字节) + 一个int整形(4字节), 按照预想应该是 5字节,但是实际结果却是 8 字节。
二 ,解释(具体对齐规则)
1. 内存对齐数
要正确计算结构体 总大小,首先要了解 内存对齐数 -- 一个结构体的内存对齐数 由其 成员决定,每一个成员都有自己的内存对齐数(如果是基本类型,内存对齐数是本身大小),结构体的内存对齐数为 其内部成员中最大的内存对齐数 。
如 :struct B{ char c; int a;} 中 结构体 B的内存对齐数为 4 (c 的 内存对齐数 1 < a 的内存对齐数4 )
若 内部包含 结构体 成员 呢 ?
如 :struct B{ char c; int a;} struct C{char c;struct B b;}
结构体 C的内存对齐数为 4 ( c 的 内存对齐数 1 < b 的内存对齐数 4 )
2. 开始实际计算
知道一个 结构体的内存对齐数 后 ,便可以开始计算 结构 体 的大小
计算规则就是 ,按成员 声明的顺序开始计算 :保证每个成员 都 在 自己内存对齐数 倍数位置处 开始占用内存 。如下图
例一:
struct A
{// 空间占用 对齐数char c; // 0 -- 123 1 (在第0位置处开始占用, 从 1 位置处开始补齐三个字节 ,使 a 能够在 第 4 位置处开始占用 )int a; // 4 5 6 7 4 (在第 4 位置处开始占用,正常占用 4 个 字节)char c1; // 8 1 (在第 8 位置处开始占用,正常占用 1 个 字节)char c2; // 9 1 (在第 9 位置处开始占用,正常占用 1 个 字节)char c3; // 10 -- 11 1 (在第10位置处开始占用, 从 11位置处开始补齐 1 个字节 使 b 能够在第 12 位置处开始占用)int b; // 12 13 14 15 4 (在第 12 位置处开始占用,正常占用 4 个 字节)// b2对齐数 4 int b2; // 16 17 18 19 -- 20 21 22 23 (在第16位置处开始占用, 从 20位置处开始补齐 4 个字节 使 d 能够在第 24 位置处开始占用)// d 对齐数 8double d; // 24 25 26 27 28 29 30 31 (在第 24 位置处开始占用,正常占用 8 个 字节)
};
int main()
{printf("%d\n", sizeof(struct A));return 0;
}
例二 :
(注 : 结构体的内存对齐数为 其内部成员中最大的内存对齐数 )
struct A
{// 空间占用 对齐数char c; // 0 -- 123 1 (在第0位置处开始占用, 从 1 位置处开始补齐三个字节 ,使 a 能够在 第 4 位置处开始占用 )int a; // 4 5 6 7 4 (在第 4 位置处开始占用,正常占用 4 个 字节)char c1; // 8 1 (在第 8 位置处开始占用,正常占用 1 个 字节)char c2; // 9 1 (在第 9 位置处开始占用,正常占用 1 个 字节)char c3; // 10 -- 11 1 (在第10位置处开始占用, 从 11位置处开始补齐 1 个字节 使 b 能够在第 12 位置处开始占用)int b; // 12 13 14 15 4 (在第 12 位置处开始占用,正常占用 4 个 字节)// b2对齐数 4 int b2; // 16 17 18 19 -- 20 21 22 23 (在第16位置处开始占用, 从 20位置处开始补齐 4 个字节 使 d 能够在第 24 位置处开始占用)// d 对齐数 8double d; // 24 25 26 27 28 29 30 31 (在第 24 位置处开始占用,正常占用 8 个 字节)
};
struct B
{// 空间占用 对齐数int a; // 0 1 2 3 4 (在第0位置处开始占用)char c; // 4 -- 5 1 (在第4位置处开始占用, 从 5 位置处开始补齐 1 个字节 使 d 能够在第 6 位置处开始占用)short b; // 6 7 2 (在第6位置处开始占用)struct A ad; // 8 .. 39 8 (在第8位置处开始占用)
};
int main()
{printf("%d\n", sizeof(struct A));printf("%d\n", sizeof(struct B));return 0;
}
例三:
注意 : 最终结构体 的大小 要在满足所有结构体成员对齐的情况下,还要是 结构体成员内存对齐数 的 最大值 的倍数 (这里 就是 4 的 倍数 ,所以 总占用为 5+3(补) = 8
struct A // 对齐数 空间占用
{ int a; // 4 0 1 2 3 (从0位置开始占用 4 个字节)char c; // 1 1 (从 1 位置开始占用 1 个字节)// 但是最终结构体 的大小 要为 结构体成员内存对齐数 的 最大值 的倍数 (这里 就是 4 的 倍数 ,所以 总占用为 5+3(补) = 8
};
int main()
{printf("%d\n", sizeof (struct A));return 0;
}