C 为什么允许在结构中使用未定义的大小数组?

C 为什么允许在结构中使用未定义的大小数组?,c,C,当我编写以下代码时,我得到了预期的错误错误:“data”中缺少数组大小 int main() { unsigned char data[]; return 0; } 但是,当我运行相同的代码,但将有问题的行包装到结构中时,没有错误 typedef struct credit_card_s { unsigned char is_valid; unsigned char data[]; } credit_card_t; 有人能解释一下为什么允许这样做吗?后者被称为a

当我编写以下代码时,我得到了预期的错误
错误:“data”中缺少数组大小

int main()
{
    unsigned char data[];

    return 0;
}
但是,当我运行相同的代码,但将有问题的行包装到
结构中时,没有错误

typedef struct credit_card_s
{
  unsigned char is_valid;

  unsigned char data[];

} credit_card_t;
有人能解释一下为什么允许这样做吗?

后者被称为a,这是结构的特例。结构的最后一个成员不允许有大小

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

另见

前者是普通数组,不允许大小为零。看

如果它们限定表达式(指定数组大小),则表达式应为整数类型。如果表达式是常数表达式,则其值应大于零。 换句话说,语言标准是这样说的

在第一个示例中,您定义了一个正则数组,但没有给出其大小。 这在C中是不合法的。在
结构之外
,声明数组时需要一个大小,因为以后无法设置大小:

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

  return 0;
}
在第二个示例中,您定义了一个。 这是C语言中的合法操作,允许您在为
结构分配内存时为数组分配内存。灵活数组成员必须是
结构中的最后一个元素

以下是一个基于以下内容的示例:


你的意思是说“未指定的数组大小”。(题外话:你能取消删除吗?我写了一个答案,我觉得很有趣,但你在我完成之前几分钟就删除了它。在这里发表评论是因为没有地方对已删除的帖子发表评论)@PeterCordes它已取消删除技术上,它不是零长度数组。专有名称为flexible数组成员。在C标准添加灵活的数组成员(使用
[]
)之前,GCC允许零长度数组(使用
[0]
)作为语言扩展。虽然编译器在报告结构的大小时将其视为零大小,但在为结构分配存储时,通常预期其大小为非零。@EricPostChil感谢提供更多信息!我据此编辑了我的答案。
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;