【问题标题】:C Sizeof char[] in struct [closed]结构中的C Sizeof char [] [关闭]
【发布时间】:2020-01-23 14:43:23
【问题描述】:

我知道填充是什么以及对齐的工作原理。给定以下结构:

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) 它返回16

编辑:我明白了。

【问题讨论】:

  • 您的解释和变量名不匹配。没有c
  • 你从哪里得到四个字节的填充?谁说这个结构需要填充?
  • 抱歉变量错误,我编辑了问题,您发布链接的问题没有回答我的问题。
  • 我不确定链接的问题是否能回答这个问题。但是,简而言之,如果以下字段需要它,您只有填充。短只需要填充到偶数地址(resp。偏移量),您在偶数大小的数组之后拥有该地址。并且它后面的 int 需要一个可以被 4 整除的偏移量,它具有。并且整个结构只需要一个长度模其最长的单一类型(即 4),消除最后的填充需要。 16的长度就很好了。
  • 没有行。一个结构包含它的所有成员,在内存中按顺序排列(可能在它们之间有填充),它们都是相互分离的。工会与成员重叠。在联合中,所有 成员是重叠的。要获得一个聚合,其中一些成员单独布局,一些成员重叠,您必须使用包含结构的联合。

标签: c struct byte sizeof


【解决方案1】:

在结构中

struct {
    char word[10];
    short a;
    int b;  
}

您有以下要求:

  • a 需要一个均匀的偏移量。由于 char 数组在其长度之前是偶数,因此不需要填充。所以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

【讨论】:

  • 谢谢,我想我现在明白了。
【解决方案2】:

在:

struct
{
    char word[10];
    short a;
    int b;  
}

给定两字节short和四字节int,结构在内存中布局:

抵消成员 0 字[0] 1 个字[1] 2 字[2] 3 字[3] 4字[4] 5字[5] 6字[6] 7字[7] 8字[8] 9字[9] 10个 11个 12 乙 13 乙 14 乙 15 乙

要获得问题中描述的布局,其中ab 重叠word,您需要在struct 内使用union

typedef union
{
    char word[10];
    struct { short a; int b; };
} Test;

【讨论】:

    【解决方案3】:

    通常,每个变量都会在其大小的边界上对齐。
    (除非应用了 packed 等属性)

    完整的讨论在Wikipedia,其中部分内容是:

    一个字符(一个字节)将是 1 字节对齐的。
    一个短的(两个字节)将是 2 字节对齐的。
    一个 int(四个字节)将是 4 字节对齐的。
    long(四个字节)将是 4 字节对齐的。
    浮点数(四个字节)将是 4 字节对齐的。
    双精度(8 字节)将在 Windows 上对齐 8 字节,在 Windows 上对齐 4 字节 Linux(8 字节,带有 -malign-double 编译时间选项)。
    long long(8 个字节)将 4 字节对齐。

    所以你的结构布局为:

    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的顺序,你会看到结构的大小发生了变化。

    【讨论】:

    • 每个变量必须在其大小的边界上对齐。除非它被打包。
    • "每个变量必须在其大小的边界上对齐。"嗯?没有。
    • 每个 C 实现都有自己的对齐规则。它们不需要是对象大小的函数。
    猜你喜欢
    • 1970-01-01
    • 2014-07-21
    • 2010-12-26
    • 2012-12-27
    • 1970-01-01
    • 2017-04-02
    • 1970-01-01
    • 2018-11-21
    • 1970-01-01
    相关资源
    最近更新 更多