结构中的 C Sizeof char[]
C Sizeof char[] in struct
我知道填充是什么以及对齐是如何工作的。给定以下结构:
typedef struct {
char word[10];
short a;
int b;
} Test;
我不明白 C 如何解释和对齐结构中的 char 数组。应该是9个字符+终止符,应该算是最长的了,像这样:
| - _ - _ - _ - _ - word - _ - _ - _ - _ - |
| - a - | - _ - b - _ - | padding the remaining 4 bytes
“-”代表一个字节,“_”分隔字节。所以我们有 10 个字节长的字,2 个字节长的 a 和 4 个字节长的 b 和 4 个字节的填充。但是当我打印 sizeof(Test) 它时 returns 16
.
编辑:我明白了。
一般来说,每个变量都会在其大小的边界上对齐。
(除非应用packed
等属性)
Wikipedia 上有完整的讨论,部分内容是:
A char (one byte) will be 1-byte aligned.
A short (two bytes) will be 2-byte aligned.
An int (four bytes) will be 4-byte aligned.
A long (four bytes) will be 4-byte aligned.
A float (four bytes) will be 4-byte aligned.
A double (eight bytes) will be 8-byte aligned on Windows and 4-byte aligned on
Linux (8-byte with -malign-double compile time option).
A long long (eight bytes) will be 4-byte aligned.
因此您的结构布局如下:
typedef struct {
char word[10];
// Aligned with beginning of structure; takes bytes 0-9
short a;
// (assuming short is 2-bytes)
// Previous member ends on byte 9, this one starts on byte-10.
// Byte 10 is a multiple of 2, so no padding necessary
// Takes bytes 10 and 11
int b;
// Previous member ends on byte 11, next byte is 12, which is a multiple of 4.
// No padding necessary
// Takes bytes 12, 13, 14, 15.
} Test;
总大小:16 字节。
如果你想玩它,把你的单词数组改成 9 或 11 个字节,
或者颠倒 short
和 int
的顺序,您会看到结构的大小发生变化。
在:
struct
{
char word[10];
short a;
int b;
}
并给定两个字节short
和四个字节int
,结构在内存中的布局:
Offset Member
0 word[0]
1 word[1]
2 word[2]
3 word[3]
4 word[4]
5 word[5]
6 word[6]
7 word[7]
8 word[8]
9 word[9]
10 a
11 a
12 b
13 b
14 b
15 b
要获得问题中描述的布局,其中 a
和 b
重叠 word
,您需要在 union
中使用 struct
:
typedef union
{
char word[10];
struct { short a; int b; };
} Test;
在类似
的结构中
struct {
char word[10];
short a;
int b;
}
您有以下要求:
a
需要偶数偏移。由于之前的字符长度是偶数,因此不需要填充。所以 a
位于偏移量 10。
b
需要一个可以被 4 整除的偏移量。12 可以被 4 整除,所以 12 是 b
. 的一个很好的偏移量
整个结构需要一个可以被 4 整除的大小,因为这个结构数组中的每个 b
都需要满足上述要求。但由于我们目前的尺寸为 16,因此我们不需要任何填充。
WWWWWWWWWWAABBBB
|-- 10 --| 2 4 = 16
与
比较
struct {
char word[11];
short a;
int b;
}
此处,a
的偏移量为 11。这是不允许的,因此会插入填充。 a
偏移量为 12 即可。
b
将得到 14 的偏移量,这也是不允许的,因此添加了 2 个字节。 b
获得 16 的偏移量。整个结构的大小为 20,这对于数组中的所有后续项都很好。
WWWWWWWWWWW.AA..BBBB
|-- 11 --|1 2 2 4 = 20
第三个例子:
struct {
char word[11];
int b;
short a;
}
(注意顺序改变了!)
b
对偏移量 12 很满意(它得到 1 个填充字节),
a
对偏移量 16 感到满意。(前面没有填充。)
然而,在结构之后,添加了 2 个字节的填充,以便结构与 4 对齐。
WWWWWWWWWW..BBBBAA..
|-- 10 --| 2 4 2 2 = 20
我知道填充是什么以及对齐是如何工作的。给定以下结构:
typedef struct {
char word[10];
short a;
int b;
} Test;
我不明白 C 如何解释和对齐结构中的 char 数组。应该是9个字符+终止符,应该算是最长的了,像这样:
| - _ - _ - _ - _ - word - _ - _ - _ - _ - |
| - a - | - _ - b - _ - | padding the remaining 4 bytes
“-”代表一个字节,“_”分隔字节。所以我们有 10 个字节长的字,2 个字节长的 a 和 4 个字节长的 b 和 4 个字节的填充。但是当我打印 sizeof(Test) 它时 returns 16
.
编辑:我明白了。
一般来说,每个变量都会在其大小的边界上对齐。
(除非应用packed
等属性)
Wikipedia 上有完整的讨论,部分内容是:
A char (one byte) will be 1-byte aligned.
A short (two bytes) will be 2-byte aligned.
An int (four bytes) will be 4-byte aligned.
A long (four bytes) will be 4-byte aligned.
A float (four bytes) will be 4-byte aligned.
A double (eight bytes) will be 8-byte aligned on Windows and 4-byte aligned on Linux (8-byte with -malign-double compile time option).
A long long (eight bytes) will be 4-byte aligned.
因此您的结构布局如下:
typedef struct {
char word[10];
// Aligned with beginning of structure; takes bytes 0-9
short a;
// (assuming short is 2-bytes)
// Previous member ends on byte 9, this one starts on byte-10.
// Byte 10 is a multiple of 2, so no padding necessary
// Takes bytes 10 and 11
int b;
// Previous member ends on byte 11, next byte is 12, which is a multiple of 4.
// No padding necessary
// Takes bytes 12, 13, 14, 15.
} Test;
总大小:16 字节。
如果你想玩它,把你的单词数组改成 9 或 11 个字节,
或者颠倒 short
和 int
的顺序,您会看到结构的大小发生变化。
在:
struct
{
char word[10];
short a;
int b;
}
并给定两个字节short
和四个字节int
,结构在内存中的布局:
Offset Member 0 word[0] 1 word[1] 2 word[2] 3 word[3] 4 word[4] 5 word[5] 6 word[6] 7 word[7] 8 word[8] 9 word[9] 10 a 11 a 12 b 13 b 14 b 15 b
要获得问题中描述的布局,其中 a
和 b
重叠 word
,您需要在 union
中使用 struct
:
typedef union
{
char word[10];
struct { short a; int b; };
} Test;
在类似
的结构中struct {
char word[10];
short a;
int b;
}
您有以下要求:
a
需要偶数偏移。由于之前的字符长度是偶数,因此不需要填充。所以a
位于偏移量 10。b
需要一个可以被 4 整除的偏移量。12 可以被 4 整除,所以 12 是b
. 的一个很好的偏移量
整个结构需要一个可以被 4 整除的大小,因为这个结构数组中的每个
b
都需要满足上述要求。但由于我们目前的尺寸为 16,因此我们不需要任何填充。WWWWWWWWWWAABBBB |-- 10 --| 2 4 = 16
与
比较struct {
char word[11];
short a;
int b;
}
此处,a
的偏移量为 11。这是不允许的,因此会插入填充。 a
偏移量为 12 即可。
b
将得到 14 的偏移量,这也是不允许的,因此添加了 2 个字节。 b
获得 16 的偏移量。整个结构的大小为 20,这对于数组中的所有后续项都很好。
WWWWWWWWWWW.AA..BBBB
|-- 11 --|1 2 2 4 = 20
第三个例子:
struct {
char word[11];
int b;
short a;
}
(注意顺序改变了!)
b
对偏移量 12 很满意(它得到 1 个填充字节),
a
对偏移量 16 感到满意。(前面没有填充。)
然而,在结构之后,添加了 2 个字节的填充,以便结构与 4 对齐。
WWWWWWWWWW..BBBBAA..
|-- 10 --| 2 4 2 2 = 20