- 论坛徽章:
- 11
|
本帖最后由 zylthinking 于 2011-11-22 14:20 编辑
我也来说说看法,不对的地方请大家指出来。谢谢
1. sizeof 一个 结构体,说的的数据 和
结构体的布局是有 ...
keytounix 发表于 2011-11-21 22:23 ![]()
被这个基本问题真的搞昏头了, 而且这个概念甚至是多年前就有的, 居然一直都是迷迷瞪瞪状态
做了几个不全面的实验, 有几个结论
1. 首先 gcc 这个 __attribute((aligned(x))) 和 VC 的 #pragma pack(x) 不是仅仅是拼写上的区别
微软规则是结构体自身的对齐原则是 x 与成员对齐值取其小者
因此这样的结构
#pragma pack(4)
4 struct A{
5 char a;
6 char b;
7 char c;
8 };
#pragma pack()
结构体自身对齐值仍为 1, sizeof 的结果照旧是 3, 因此微软的存在一个默认 aligin 的概念, 32位上一般是 4
gcc 同样支持 #pragma pack, 而且语意相同, 但不同的是, 不存在默认 align(x) 这个论断
4 struct A{
5 char a;
6 char b;
char c;
7 //};---------------------------------------------sizeof == 3
8 }__attribute__((aligned(4))); -----------sizeof == 4
9
这个__attribute__((aligned(4))) 似乎强调的是整个结构体就是4字节对齐, 或者至少是4 << N 对齐, 这样其实也是 4 字节对齐, 只不过恰好是倍数而已。
如果 aligned(x) 和 #prama pack 合用, 区别就很明显了
16 #pragma pack(2)
17
18 struct C{
19 char c;
20 double d;
21 }__attribute__((aligned(4)));
22 #pragma pack()
23
经验证, d 确实2字节对齐的, 但 sizeof(C) 确实 12, 意味着, double d 后存在两个 padding
考虑到数组的地址连续需要保证, 因此对结构体长度的要求也应该是保证数组中下一个元素也能达到其自身对齐要求。
如果数组中每一项都达到对齐要求, 需要的是每一项长度应该都是对齐值的整数倍, 也就是说, sizeof(A) % alignof(A) == 0
再考虑A自身对齐, 如果其中某个成员 m, 则要求 (N * alignof(A) + offsetof(m)) % alignof(m) == 0;
因为 offsetof(m) 是固定的, 如果 offsetof(m) % alignof(m) != 0,
则 offsetof(m) > 0, (k * alignof(A) + offsetof(m)) % alignof(m) == 0; (k >= 1)
并且 ((k + 1) * alignof(A) + offsetof(m)) % alignof(m) == 0; 因此 alignof(A) % alignof(m) == 0
因此 offsetof(m) % alignof(m) == 0, 和假设矛盾, 因此假设错误,
因此必有 offsetof(m) % alignof(m) == 0, 那么则 N * alignof(A) % alignof(m) == 0, 设 N == 1,
结论1: 则alignof(A) % alignof(m) == 0,既然 m 是 alignof(m) 是任意的 (2, 4, 8 ..) 要达到要求, 必然 alignof(A) 是结构体中最大成员对齐值, 并且 sizeof(A) 必然是 alignof(A) 的整数倍
下面分析一个例子, 看看是不是, 两个 sizeof 都是输出 8, 对齐值没计算(头已经晕了):
3
4 struct x{
5 char a;
6 char b;
7 char c;
8 //};
9 }__attribute__((aligned( 8 )));
10
根据之前对 __attribute__ 的理解, 他的align 值是 8;(或者16, 32.... 这个需要再琢磨一个例子出来验证), sizeof 是8的整数倍, 并满足 >= 3, 则也是 8
11 struct A
12 {
13 char a;
14 char b;
15 struct x c[0];
16 //};
17 }__attribute__((aligned(4)));
18
A 按理说应该是 4对齐(或者8, 16.... 这个需要再琢磨一个例子出来验证),
按结论1: A对齐值需要是成员中最大的, 不过不考虑c, 则很显然 4即满足; 但c[0] 要求后面跟着的x按x自身对齐, 而 b 和 c 之间因为 c对齐存在空洞应该算在A上面, 其实就是和
11 struct A
12 {
13 char a;
14 char b;
15 struct x c;
16 //};
17 }__attribute__((aligned(4)));
18
一个意义, 既然将 c 看作其中一个成员, 那么按结论1, A 的对齐值应该是x 的对齐值, 也就是 8, sizeof(A) 是 sizeof(X)的整数倍, 返回 c[0], 即减去一个sizeof(X), 那么剩下的还是 sizeof(X)的整数倍, 因此是8
那么
11 struct A
12 {
13 char a;
14 char b;
15 struct x c[0];
16 };
sizeof 是多少呢, 按上面分析, 应该和上面一样, 实际验证是正确的。
验证环境: ubuntu 8.04 x86 32位 |
|