【问题标题】:sizeof() a struct with a zero length array membersizeof() 具有零长度数组成员的结构
【发布时间】:2020-01-15 12:18:51
【问题描述】:

我对 C 中的 sizeof() 输出感到困惑。假设我有:

struct foo {
    char a;
    char b;
    char c;
    char d[0];
};

我希望sizeof(struct foo) 为 4。但是,它在使用 gcc 编译后返回 3。此外,在使用严格设置 -pedantic-errors 编译代码时,我得到编译器错误。

谁能帮我理解这种行为?

【问题讨论】:

  • 如果您将0 更改为1 或更高版本会怎样?
  • 声明一个包含 0 个元素的数组是无效的 C。它被 GCC(和其他一些实现)作为扩展接受。
  • 你能把它标记为 CW 吗?这似乎是一个不错的 C 常见问题解答候选者。
  • 我冒昧地在帖子中添加了一些额外的信息,因为现在有人已将此问题添加到 C FAQ。我希望你不要介意 - 这只是意味着你的问题会得到积极的额外关注。

标签: c gcc sizeof c99 flexible-array-member


【解决方案1】:

数组大小为 0 是不合法的。 C standard 的第 6.7.6.2p1 节关于数组声明器状态:

除了可选的类型限定符和关键字 static 之外,[] 可以分隔表达式或 *如果他们分隔了一个表达式(它指定了数组的大小),则该表达式应为整数类型。如果表达式 是一个常量表达式,它的值应该大于零。 元素类型不应是不完整或函数类型。这 可选类型限定符和关键字 static 应出现 仅在带有数组的函数参数声明中 类型,然后只在最外层的数组类型推导。

所以因为这违反了约束,所以这个定义调用了undefined behavior

话虽如此,一些编译器允许零长度数组作为 struct 的最后一个成员作为扩展名。 GCC does this。在这种情况下,它的工作方式与灵活数组成员相同。

执行此操作的标准兼容方法是将尺寸留空:

struct foo {
    char a;
    char b;
    char c;
    char d[];
};

在这两种情况下,灵活数组成员都不包含在结构的大小中,这就是为什么你得到 3 而不是 4 的大小(尽管结构中是否存在填充取决于实现)。这也意味着这样的结构不能是数组的成员(至少在没有一些可疑的手动指针操作的情况下不能)。

使用这种结构的方式是为它动态分配空间以及最后一个成员的一些元素。例如:

struct foo *my_foo = malloc(sizeof(*my_foo) + (sizeof(char) * number_of_elements));

【讨论】:

  • 这是不合法的,但实际上是作为GNU extension实现的。
  • 啊,有道理。那么 gcc 是否将其解释为指向结构末尾的指针?
  • @marcantonio 它实际上指向灵活数组成员,它位于其他成员之后。
  • 灵活数组成员语法在 C99 中被标准化,但在此之前的几个编译器(例如 GCC 和 MSVC)通过使用 0 作为数组的预标准语法支持它长度。那些编译器在标准语法上窒息。
【解决方案2】:

char d[0] 是一个大小为 0 的字符数组。这意味着它不占用任何空间,因为 sizeof(char) * 0 = 0

【讨论】:

  • 通常数组会衰减为指向&d[0] 的指针,但由于您使用的是零大小数组,因此该元素不存在。所以我不太确定。
  • 衰变在这里有什么意义?
  • @R.. 在上面的评论中被问到目前已被删除。
猜你喜欢
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 2021-03-02
  • 2020-04-13
相关资源
最近更新 更多