【问题标题】:Constant structure with flexible array members具有灵活数组成员的常量结构
【发布时间】:2012-11-22 17:18:47
【问题描述】:

请考虑以下两种结构:

typedef struct { 
    int num_data;
    char * name_data;
    int data[]; 
} part_t; 
typedef struct { 
    int num_parts;
    char * name_parts;
    part_t parts[]; 
} container_t; 

理想情况下,我可以像这样初始化一个容器:

const container_t container = { 
    2,
    "Name of first container", 
    { 
            { 4, "Name of first part", { 1, 2, 3, 4 } }, 
            { 5, "Name of first part", { 1, 2, 3, 4, 5 } } 
    } 
};

我的编译器说:“错误:初始化器太多”

【问题讨论】:

  • 这甚至不是一个简单的可变长度结构的工作原理......先尝试一个更简单的例子。
  • 这是一个“灵活的数组成员”而不是 VLA。
  • 简而言之:您无法初始化灵活的数组成员,并且拥有一个带有灵活数组成员的structs 数组是等待发生的索引灾难。
  • @DanielFischer:从概念上讲,它并不比int foo[] = {1,2,3,4}; 差,如果允许的话,我肯定遇到过这样的事情会很有用的地方。如果某些编译器允许这样的构造,我不会感到惊讶,因为很清楚任何可以处理它的编译器上的语义“应该是”[在初始化数据区域中分配适当数量的空间,让结构名称代表一个在地址处的左值,并且 sizeof(structname) 等于分配的大小]。尽管该功能很有用,但我不知道它是否有用到足以证明实施它的合理性。
  • @supercat 你只是在谈论初始化一个灵活的数组成员,我猜?是的,这有时会很有用,但这意味着类型取决于灵活数组成员的长度,那么您将拥有 struct foo<N>(借用一点 C++ 模板符号)。如果实现支持 VLA,我想有可能实现。但这将是对语言的重大改变。

标签: c struct constants variable-length-array


【解决方案1】:

ISO/IEC 9899:2011 §6.7.2.1 结构和联合说明符

3 结构或联合不应包含不完整或函数类型的成员(因此, 结构不应包含自身的实例,但可以包含指向实例的指针 本身),除了具有多个命名成员的结构的最后一个成员 可能有不完整的数组类型;这样的结构(以及任何包含,可能 递归地,作为这种结构的成员)不应是结构的成员或 数组的元素。

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

问题是您不能将具有灵活数组成员的结构嵌入到数组或其他结构中。您可以拥有指向此类结构的指针,但不能拥有此类结构的实例。

【讨论】:

  • 有趣的是,CERT 说具有灵活数组成员 的结构可以用作另一个结构的最后一个成员;但他们没有在这一点上引用标准。在编号列表的第 3 点中提到:securecoding.cert.org/confluence/display/c/…
  • C 标准机构正在讨论它。请参阅 WG14 网站上PrePittsburgh2016 邮件中的 N2083。到目前为止,它是不合法的; CERT 充其量只是抢先一步。
  • 感谢您的指点。我对 CERT 文件发表了评论。
  • 这是挑剔的,但我认为允许将具有灵活数组成员的结构嵌入到联合中。我所见过的任何地方都没有明确禁止它,引用的第 3 段暗示当它声明“任何包含,可能递归地包含这种结构的成员的联合”时,它是允许的。
  • Nits 值得被挑选,@ov2k,这也不例外。我认为您可能是对的;我已经相应地修改了文本(并修复了“an an”的外观)。
猜你喜欢
  • 1970-01-01
  • 2020-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-21
  • 2011-07-25
  • 2011-03-04
  • 2020-02-10
相关资源
最近更新 更多