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

问题描述 投票:0回答:2

当我编写以下代码时,我收到预期的错误

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 memory-management
2个回答
7
投票

后者称为“灵活数组成员”,这是结构的特例。结构体的最后一个成员允许没有指定的大小。

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

另请参阅示例 20

前者是普通数组,大小不允许为零。请参阅 6.7.6.2 数组声明符

如果它们分隔表达式(指定数组的大小),则该表达式应具有整数类型。如果表达式是常量表达式,则其值应大于零。 换句话说,语言标准是这么说的。


3
投票

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

这在 C 中是不合法的。在

struct
之外,声明数组时需要一个大小,因为以后无法设置大小:

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

  return 0;
}

在第二个示例中,您定义了一个灵活的数组成员

这是 C 中的合法操作,允许您在为

struct
分配内存时为数组分配内存。灵活数组成员必须是
struct
中的最后一个元素。

这是一个示例,基于 GCC 文档中的示例

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;
© www.soinside.com 2019 - 2024. All rights reserved.