首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这种具有灵活数组成员的结构初始化无效,但对于固定大小的数组成员有效?

为什么这种具有灵活数组成员的结构初始化无效,但对于固定大小的数组成员有效?
EN

Stack Overflow用户
提问于 2020-07-07 11:09:21
回答 3查看 326关注 0票数 3

C标准规定(强调我的标准):

21声明后的21示例2: 结构s{ int n;双d[];}; 结构s具有灵活的数组成员d。..。

22在上述声明之后:

结构s t1 ={0 };//有效结构s t2 ={ 1,{ 4.2 };//无效t1.n = 4;//有效t1.d = 4.2;//可能是未定义的行为。

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

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

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

如果我使用{ 1, { 4.2 }};的初始化器,那么{ 4.2 }部分就是初始化柔性数组成员;准确地说,初始化由一个元素组成的柔性数组成员并将该元素初始化为值4.2,因此stuct s被视为有成员d吗?

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

  • 为什么标准说,{ 4.2 }不会初始化/表示灵活的数组成员,因此结构将被视为没有成员d

如果我使用固定大小数组,则此表示法工作并初始化成员,没有任何抱怨:

代码语言:javascript
复制
struct foo {
    int x;
    double y[1];
};

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

证据

  • 为什么这种初始化在结构具有灵活的数组成员时无效,而当结构有固定大小的数组成员时有效?

你能详细说明一下吗?

我读过:

为什么柔性数组成员的静态初始化工作?

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

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

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

相关信息:

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-07-07 12:10:07

我想这是语言缺陷。虽然初始化一个灵活的数组成员可能没有意义,但是标准需要在某个地方解决这个问题。我在任何地方都找不到这样的规范文本。

灵活数组成员的定义是,C17 6.7.2.1/18:

作为特例,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型;这称为灵活数组成员。在大多数情况下,灵活的数组成员会被忽略。特别是,结构的大小似乎省略了灵活的数组成员,只是它可能有比省略所暗示的更多的尾部填充。

由此我们了解到,灵活的数组成员是不完整的数组类型。但是,除了计算结构的大小时,我们不了解在什么情况下忽略灵活数组成员。“在大多数情况下”是没有帮助的,也是缺点--这需要扩展到一个详尽的列表中,包括在初始化程序列表的一部分时灵活数组成员的行为。否则,人们可能会假设它的行为就像任何其他不完整类型的数组一样。

C17 6.2.5/22:

大小未知的数组类型是不完全类型。

然后初始化的规则是,C17 6.7.9:

要初始化的实体的类型应该是未知大小的数组,或者不是可变长度数组类型的完整对象类型。

到目前为止,还没有规范性的文本说我们不允许为一个灵活的数组成员提供一个初始化器--恰恰相反。问题中的示例(C17 6.7.2.1示例21)不是规范性的,因为在国际标准化组织标准中示例是不规范的。该示例没有提到违反了哪个约束,也没有提到它说必须忽略灵活数组成员的地方。

我想我可能会向医生报告这件事。

票数 2
EN

Stack Overflow用户

发布于 2020-07-07 11:55:05

我不明白“因为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是实际上不存在的东西的初始化程序。

为什么是这种情况是明智的。在大多数情况下,我希望编译器能够支持一个定义,在定义中对数组初始化器进行计数并使用它来设置结构大小。当然,编译器是用数组定义(如int a[] = { 3, 4, 5}; )来实现这一点的。但是,这并不是灵活数组成员的典型用例。通常情况下,程序接收关于它需要与结构一起管理多少元素的信息,为结构分配空间,为这些元素分配空间,然后在分配的空间中放置一个结构。也就是说,具有灵活数组成员的结构的典型用例是具有动态分配空间的。我希望C委员会认为没有必要要求编译器支持静态或自动对象中的灵活数组成员,而不是动态对象。

票数 2
EN

Stack Overflow用户

发布于 2020-07-07 14:10:15

在您引用的示例中,您省略了一些重要的语言--以下是全文:

20声明后的示例2:struct s{ int n;double d[];}; 结构struct s有一个灵活的数组成员d.。一种典型的使用方法是:int m= /* some */;struct *p = malloc(sizeof (struct s) + sizeof (double m)); 假设对malloc p 的调用成功,则在大多数情况下,p指向的对象的行为就好像 p 已声明为:struct{ int n;double dm;}*p;E 229 d (在某些情况下,这种等价性被破坏;特别是成员的抵消可能不一样)。

IOW,只有在动态分配struct实例并为数组成员分配额外空间时,灵活的数组成员才真正发挥作用。

灵活的数组成员没有大小,因此它不会对struct类型的大小有所贡献--也就是说,sizeof (struct s)的结果计算为没有数组的类型的大小。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62773931

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档