【问题标题】:Why is undefined size array in struct allowed?为什么允许结构中未定义大小的数组?
【发布时间】:2018-08-18 20:28:06
【问题描述】:

当我编写以下代码时,我得到了预期的错误error: array size missing in 'data'

int main()
{
    unsigned char data[];

    return 0;
}

但是,当我运行相同的代码但将有问题的行包含在 struct 中时,没有错误。

typedef struct credit_card_s
{
  unsigned char is_valid;

  unsigned char data[];

} credit_card_t;

谁能向我解释为什么允许这样做?

【问题讨论】:

标签: c


【解决方案1】:

后者称为"flexible array member",这是结构的特殊情况。结构的最后一个成员可以没有大小。

作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型;这称为灵活数组成员。在大多数情况下,灵活数组成员被忽略。特别是,结构的大小就像省略了柔性数组成员一样,只是它可能具有比省略所暗示的更多的尾随填充。然而,当一个 . (或 -> )运算符的左操作数是(指向)具有灵活数组成员的结构,右操作数命名该成员,它的行为就像该成员被替换为最长的数组(具有相同的元素类型) 不会使结构大于被访问的对象;数组的偏移量应保持灵活数组成员的偏移量,即使这与替换数组的偏移量不同。如果这个数组没有元素,它的行为就好像它有一个元素,但是如果尝试访问该元素或生成一个越过它的指针,则行为是不确定的。

另见example 20

前者是一个普通数组,它的大小不允许为零。见6.7.6.2 Array declarators

如果他们界定了一个表达式(它指定了一个数组的大小),那么该表达式应该是一个整数类型。如果表达式是常量表达式,则它的值应大于零。 换句话说,语言标准是这样说的。

【讨论】:

    【解决方案2】:

    在您的第一个示例中,您定义了一个常规数组,但没有给出其大小。

    这在 C 中是不合法的。在 struct 之外,您的数组在声明它时需要一个大小,因为您以后无法设置大小:

    int main()
    {
      unsigned char data[100];
    
      return 0;
    }
    

    在第二个示例中,您定义了 flexible array member

    这是 C 中的合法操作,允许您在为 struct 分配内存时为数组分配内存。灵活数组成员必须是struct 中的最后一个元素。

    这是一个基于the one from GCC's documentation的示例:

    struct line
    {
      int length;
      char contents[]; // Flexible array member
    };
    
    struct line *myline = malloc(sizeof(struct line) + 100); // 100 bytes for the array
    myline->length = 100;
    

    【讨论】:

    • 从技术上讲,它不是一个零长度数组。正确的名称是灵活数组成员。 在 C 标准添加灵活数组成员(使用 [])之前,GCC 允许零长度数组(使用 [0])作为语言扩展。虽然编译器在报告结构的大小时将其视为零大小,但在为结构分配存储空间时,通常期望它具有非零大小。
    • @EricPostpischil 感谢您提供更多信息!我相应地编辑了我的答案。
    猜你喜欢
    • 2019-12-20
    • 2011-06-04
    • 1970-01-01
    • 2020-02-15
    • 2020-01-28
    • 1970-01-01
    • 2015-08-26
    • 1970-01-01
    • 2019-10-02
    相关资源
    最近更新 更多