【问题标题】:Size of a struct with two void pointers is 4?具有两个 void 指针的结构的大小是 4?
【发布时间】:2010-09-16 13:54:26
【问题描述】:

我不明白为什么

struct e{
    void * a;
    void * b[];
}

有 sizeof(e) == 4 而

struct f{
    void * a;
    void * b;
}

有 sizeof(f) == 8。

【问题讨论】:

标签: c pointers struct sizeof


【解决方案1】:
struct e{
    void * a;
    void * b[];
//          ^^
}

结构中的[] 使b 成为C99“灵活数组成员”。因此sizeof(e) 将只计算a 的大小,即4。

来自 C99 §6.7.2.1/16:

作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型;这称为灵活数组成员。在大多数情况下,灵活数组成员被忽略。 特别是,结构的大小就像省略了灵活数组成员一样,只是它的尾部填充可能比省略所暗示的要多。

但是,当.(或->)运算符的左操作数是(指向)具有灵活数组成员的结构并且右操作数命名该成员时,它的行为就好像该成员是替换为不会使结构大于被访问对象的最长数组(具有相同元素类型);数组的偏移量应保持灵活数组成员的偏移量,即使这与替换数组的偏移量不同。如果这个数组没有元素,它的行为就好像它只有一个元素,但如果尝试访问该元素或生成一个越过它的指针,则行为是不确定的。

【讨论】:

  • 这是否意味着我无法访问它?
  • @Alan:不,你仍然可以访问b。
  • @Alan:不;它只是意味着 sizeof() 返回您观察到的结果。
  • @Alan:是的。您需要一个 C99 编译器,并且您需要为结构分配空间超出 sizeof 结构。如果你把它放在访问它的堆栈上,它将是 UB。
  • 通过您的 cmets 和 Wikipedia 上的“sizeof”条目,我现在掌握了它。谢谢!
【解决方案2】:

第一个结构中的第二个不是指针,而是 FAM - 灵活的数组成员。当您有一个长缓冲区并在该缓冲区的开头放置一个e 时使用它。然后,您可以使用该 FAM 索引 e 对象之后的剩余内存,并将该内存视为 void* 的数组。

标准说(我强调)

作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能 数组类型不完整;这称为灵活数组成员。在大多数情况下, 灵活的数组成员被忽略。 特别是,结构的大小就像 省略了灵活的数组成员,除了它可能有更多的尾随填充 遗漏意味着。

例如,下面的代码输出1 用于没有 GCC 的结构,但4 用于在 GCC 上具有 FAM 的结构,因为要访问整数,FAM 需要正确对齐(在这个 4 字节边界上例子)

struct A {
  char a;
};

struct B {
  char a;
  int flex[];
};

int main() {
  printf("sizeof A: %d\nsizeof B: %d\n", 
         (int)sizeof(struct A),
         (int)sizeof(struct B)
    );

  struct B *b = malloc(sizeof *b + sizeof(int[3]));
  b->a = 'X';
  b->flex[0] = 1;
  b->flex[1] = 2;
  b->flex[2] = 3;
  free(b);
}

【讨论】:

  • 由于您将各个帖子中的内容汇总并添加了示例,因此我接受了您的回答。
【解决方案3】:

这是因为第二个结构体使用了一个灵活的成员数组。 sizeof结果的解释在Wikipedia中。

【讨论】:

    【解决方案4】:

    void * b[]; 在C89 中无效,因此这意味着您正在使用C99 编译器。

    C99 引入了一种定义“struct hack”的方法:现在称为“灵活数组成员”,在分配内存之前,其大小为 0。

    【讨论】:

    • 这也很重要,因为我试图坚持使用 C89。谢谢!
    【解决方案5】:

    因为第一个没有为“b”中的指针声明任何空间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-21
      • 2014-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-08
      相关资源
      最近更新 更多