首页 > 解决方案 > 为什么对具有灵活数组成员的结构的初始化无效但对固定大小的数组成员有效?

问题描述

C标准状态(强调我的):

21示例 2声明后:

struct s { int n; double d[]; };

结构 structs具有灵活的数组成员d。[...]


22 根据上述声明:

struct s t1 = { 0 };         // valid
struct s t2 = { 1, { 4.2 }}; // invalid
t1.n = 4;                    // valid
t1.d[0] = 4.2;               // might be undefined behavior

的初始化t2无效(并且违反了约束),因为struct s它被视为不包含 memberd

资料来源:C18,§6.7.2.1/20 + /21

我不明白“因为struct s被视为不包含成员d”的解释

如果我使用 的初始化程序{ 1, { 4.2 }};,则{ 4.2 }部分是初始化灵活数组成员;准确地说,将灵活数组成员初始化为由一个元素组成,并将该元素初始化为该值4.2,因此stuct s是否将其视为具有成员d

这句话在我看来毫无意义。

如果我使用固定大小的数组,则此表示法有效并初始化成员而不会抱怨:

struct foo {
    int x;
    double y[1];
};

int main (void)
{
    struct foo a = { 1, { 2.3 } };
}

证据

你能详细说明一下吗?


我读了:

为什么灵活数组成员的静态初始化有效?

如何使用灵活的数组成员初始化结构

灵活的数组成员会导致未定义的行为吗?

和其他人,但他们都没有回答我这句话想要解释什么以及为什么这到底是无效的。


有关的:

标签: cstructinitializationlanguage-lawyerflexible-array-member

解决方案


我不明白“因为 struct s 被视为不包含成员 d”的解释。

C 标准还说“在大多数情况下,灵活的数组成员被忽略。” 不清楚为什么你不明白这是什么意思。如果struct s是声明struct s { int n; double d[]; };的,那么在大多数情况下,C 实现的行为就像是声明的一样struct s { int n; };。因此,struct s t2 = { 1, { 4.2 }};失败是因为它4.2是一个实际上不存在的东西的初始化器。

明智的做法是问为什么会出现这种情况。在大多数情况下,我希望编译器可以支持一个定义,其中数组初始值设定项被计数并用于设置结构大小。当然,编译器使用数组定义来做到这一点,例如 sint a[] = { 3, 4, 5};. 但是,这不是灵活数组成员的典型用例。通常,程序接收有关它需要使用结构管理多少元素的信息,为结构分配空间,其中包含用于这些元素的空间,然后将结构放入分配的空间中。也就是说,具有灵活数组成员的结构的典型用例是动态分配空间。我希望 C 委员会认为几乎不需要要求编译器支持静态或自动对象中的灵活数组成员,而不是动态对象。


推荐阅读