计算结构尺寸
calculating the size of structure
当我发现这个 struct
...
的大小时,我正在研究结构成员对齐和结构填充的概念
struct node{
int b;
char a;
};
... 是 8 个字节(即它包含 3 个字节的填充),而此 struct
...
的大小
struct node{
char a;
};
... 只有 1 个字节。为什么后者没有填充?
Data structure alignment.
描述的很精彩here。
假设你有这样的结构:
struct {
char a[3];
short int b;
long int c;
char d[3];
};
现在,您可能认为应该可以像这样将此结构打包到内存中:
+-------+-------+-------+-------+
| a | b |
+-------+-------+-------+-------+
| b | c |
+-------+-------+-------+-------+
| c | d |
+-------+-------+-------+-------+
但如果编译器这样安排,处理器上会容易得多:
+-------+-------+-------+
| a |
+-------+-------+-------+
| b |
+-------+-------+-------+-------+
| c |
+-------+-------+-------+-------+
| d |
+-------+-------+-------+
在“'packed'”版本中,请注意,您和我至少有点难以看到 b 和 c 字段如何环绕?简而言之,处理器也很难。因此,大多数编译器将像这样“'pad'”结构(就像有额外的、不可见的字段一样):
+-------+-------+-------+-------+
| a | pad1 |
+-------+-------+-------+-------+
| b | pad2 |
+-------+-------+-------+-------+
| c |
+-------+-------+-------+-------+
| d | pad3 |
+-------+-------+-------+-------+
此 post 解释了填充是如何完成的,而不是为什么要完成。请参考 hacks 的回答,了解为什么这样做。
记住这两条填充规则:
- 仅当结构成员后跟[=24=]一个具有更大对齐要求的成员或在end 的结构。
- 最后一个成员用所需的字节数填充,以便结构的总大小应该是任何结构成员的最大对齐的倍数。
第二个结构中的成员a
后面没有任何成员或具有更大对齐的成员,它也是最大的对齐成员,这意味着--No Padding。
阅读此 以获得更详细的解释。
struct
成员的填充和对齐完全由编译器决定,除了第一个成员之前不能有任何填充。话虽如此,编译器通常会选择填充来实现对齐目的,因此,特别是
- 有可能同一结构的所有成员同时最优对齐,并且
- 在
structs
的数组中,如果第一个数组元素的成员最佳对齐,那么所有其他元素的成员也将最佳对齐。
根据这些要求和类似要求,编译器通常会选择所需的最少填充量(理想情况下根本没有填充)。如果不同的成员类型有不同的对齐要求,那么上述考虑需要将 struct
表示填充到具有最严格对齐要求的成员大小的倍数。它们可能还需要在成员之间进行填充,具体取决于成员的类型及其顺序。
当我发现这个 struct
...
struct node{
int b;
char a;
};
... 是 8 个字节(即它包含 3 个字节的填充),而此 struct
...
struct node{
char a;
};
... 只有 1 个字节。为什么后者没有填充?
Data structure alignment.
描述的很精彩here。
假设你有这样的结构:
struct {
char a[3];
short int b;
long int c;
char d[3];
};
现在,您可能认为应该可以像这样将此结构打包到内存中:
+-------+-------+-------+-------+
| a | b |
+-------+-------+-------+-------+
| b | c |
+-------+-------+-------+-------+
| c | d |
+-------+-------+-------+-------+
但如果编译器这样安排,处理器上会容易得多:
+-------+-------+-------+
| a |
+-------+-------+-------+
| b |
+-------+-------+-------+-------+
| c |
+-------+-------+-------+-------+
| d |
+-------+-------+-------+
在“'packed'”版本中,请注意,您和我至少有点难以看到 b 和 c 字段如何环绕?简而言之,处理器也很难。因此,大多数编译器将像这样“'pad'”结构(就像有额外的、不可见的字段一样):
+-------+-------+-------+-------+
| a | pad1 |
+-------+-------+-------+-------+
| b | pad2 |
+-------+-------+-------+-------+
| c |
+-------+-------+-------+-------+
| d | pad3 |
+-------+-------+-------+-------+
此 post 解释了填充是如何完成的,而不是为什么要完成。请参考 hacks 的回答,了解为什么这样做。
记住这两条填充规则:
- 仅当结构成员后跟[=24=]一个具有更大对齐要求的成员或在end 的结构。
- 最后一个成员用所需的字节数填充,以便结构的总大小应该是任何结构成员的最大对齐的倍数。
第二个结构中的成员a
后面没有任何成员或具有更大对齐的成员,它也是最大的对齐成员,这意味着--No Padding。
阅读此
struct
成员的填充和对齐完全由编译器决定,除了第一个成员之前不能有任何填充。话虽如此,编译器通常会选择填充来实现对齐目的,因此,特别是
- 有可能同一结构的所有成员同时最优对齐,并且
- 在
structs
的数组中,如果第一个数组元素的成员最佳对齐,那么所有其他元素的成员也将最佳对齐。
根据这些要求和类似要求,编译器通常会选择所需的最少填充量(理想情况下根本没有填充)。如果不同的成员类型有不同的对齐要求,那么上述考虑需要将 struct
表示填充到具有最严格对齐要求的成员大小的倍数。它们可能还需要在成员之间进行填充,具体取决于成员的类型及其顺序。