结构中的 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 个字节, 或者颠倒 shortint 的顺序,您会看到结构的大小发生变化。

在:

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

要获得问题中描述的布局,其中 ab 重叠 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