📝 我的笔记

还没有笔记

选中页面文字后点击「高亮」按钮添加

结构体填充

📜 原文
📖 逐步解释
∑ 公式拆解
💡 数值示例
⚠️ 易错点
📝 总结
🎯 存在目的
🧠 直觉心智模型
💭 直观想象

1结构体填充

COMS W3157

Dr. Borowski

1 结构体如何存储?

```

struct my_struct {

char c;

int i;

long l;

};

struct my_struct s;

s.c = 'A';

s.i = 3000;

s.l = 123456789;

```

你将如何把 s 存储在内存中?

永远记住:一切都只是二进制位!

2 简单(错误)的方法

将每个字段一个接一个地存储。

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |

| $0 \times 41$ | $0 \times$ B 8 | $0 \times 0 \mathrm{~B}$ | $0 \times 00$ | $0 \times 00$ | $0 \times 15$ | 0xCD | $0 \times 5 \mathrm{~B}$ | $0 \times 07$ | $0 \times 00$ | $0 \times 00$ | $0 \times 00$ | $0 \times 00$ |

| char c (1 字节) | int i (4 字节) | | | | long $l$ (8 字节) | | | | | | | |

我们结构体的总大小是 $13(1+4+8)$

3 我们为什么不这样做?

这很慢!CPU 的设计目的不是在未对齐的位置读/写字节块。

解决方案:将每个结构体成员存储在其大小的倍数偏移量处。这样,CPU 可以更快地访问它。

这导致结构体内部出现空闲空间,称为填充。

4 带填充的相同结构体

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |

| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |

| $0 \times 41$ | 0x?? | 0x?? | 0x?? | 0 xB8 | 0 x 0 B | $0 \times 00$ | $0 \times 00$ |

| char c | 填充 (3 字节) | | | int i (4 字节) | | | |

| 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

| $0 \times 15$ | 0xCD | $0 \times 5 \mathrm{~B}$ | $0 \times 07$ | $0 \times 00$ | $0 \times 00$ | $0 \times 00$ | $0 \times 00$ |

| long l (8 字节) | | | | | | | |

现在每个成员都已对齐,但我们添加了 3 字节的填充,因此结构体的大小是 16。

5 结构体填充规则

注意:这些规则可能因系统而异

6 示例:
这个结构体的大小是多少?

```

struct padded_struct {

char c1;

int i1;

char c2;

int i2;

int i3;

long l;

};

```

7 示例:
这个结构体的大小是多少?

```

struct padded_struct {

char c1;

int i1;

char c2;

int i2;

int i3;

long l;

};

```

| char c1 | | | int i1 (4 字节) |

| :--- | :--- | :--- | :--- |

| char c2 | | | int i2 (4 字节) |

| int i3 (4 字节) | | | |

| long l (8 字节) | | | |

22 个有用字节 + 10 字节填充 = 32 字节!如果我们再添加一个 char 会发生什么?

8 那么数组呢?

```

struct padded_struct {

int i[3];

char c[5];

};

```

我们是将 i 对齐到 3 字节,c 对齐到 5 字节吗?

9 那么数组呢?

```

struct padded_struct {

int i[3];

char c[5];

};

```

```

struct padded_struct {

int iO, i1, i2;

char c0, c1, c2, c3, c4;

};

```

我们是将 i 对齐到 3 字节,c 对齐到 5 字节吗?

不!将 i [3] 视为 3 个不同的 int,将 c [ 5 ] 视为 5 个 char。

10 真正的挑战:嵌套结构体

```

struct A {

char c;

int i;

};

struct B {

struct A m;

int j;

};

```

结构体 B 的大小是多少?

11 嵌套结构体填充规则

```

struct A {

char c;

int i;

};

```

| char c | | |

| :--- | :---: | :--- |

| | int i | |

12 A 的大小:8 字节

```

struct B {

struct A m;

int j;

};

```

| char c | | |

| :---: | :---: | :--- | :--- |

| int i | | |

| int j | | |

结构体 A

B 的大小:12 字节

13 联合体

```

union my_union {

char c;

int i;

};

```

联合体类似于结构体,不同之处在于所有成员都存储在相同的内存位置 ⟶ 写入一个成员会覆盖其他成员。

14 联合体的大小始终是其最大类型的大小,并对齐到联合体内最大的类型。

15 最终示例

```

struct inner {

char a;

int b;

};

union my_union {

double x;

int y[2];

};

struct outer {

char flag;

struct inner i;

union my_union u;

short z;

};

```

2outer 的大小是多少?

16 最终示例

```

struct inner {

char a;

int b;

};

```

17 inner 的大小:8 字节

```

union my_union {

double x;

int y[2];

};

```

| $x$$y[0]$ 的低 4 字节 | $x$$y[1]$ 的高 4 字节 |

| :--- | :--- |

18 my_union 的大小:8 字节

```

struct outer {

char c;

struct inner i;

union my_union u;

short z;

};

```

outer 的大小:$\mathbf{4} \times \mathbf{8}=\mathbf{3 2}$ 字节