【问题标题】:Allocating struct with flexible array member使用灵活的数组成员分配结构
【发布时间】:2012-09-22 18:07:12
【问题描述】:

这是 C99 代码:

typedef struct expr_t
{
    int n_children; 
    foo data; // Maybe whatever type with unknown alignment
    struct expr_t *children[];
} expr_t;

现在,我该如何分配内存?

expr_t *e = malloc (sizeof (expr_t) + n * sizeof (expr_t *));

expr_t *e = malloc (offsetof (expr_t, children) + n * sizeof (expr_t *));

?

sizeof 是否可以保证在具有灵活数组成员的类型上工作(GCC 接受它)?

【问题讨论】:

  • 是的,它可以保证工作。 C99 §6.7.2.1/16 说“结构的大小应等于以未指定长度的数组替换灵活数组成员的其他相同结构的最后一个元素的偏移量。”。所以sizeof(expr_t) 等于offsetof(expr_t, children) 的值,如果您将children 重新定义为任意确定大小的数组。

标签: c c99 flexible-array-member


【解决方案1】:

如果编译器接受具有灵活数组成员的结构的声明,则该结构的sizeof 运算符应该产生结构的大小,就好像灵活数组成员不存在一样。

这种结构的正确分配是:

expr_t *e = malloc (sizeof(expr_t) + n * sizeof(struct expr_t *));

即使编译器不支持灵活的数组成员,您仍然可以使用此技巧。只需将结构的数组成员声明为大小为1,然后分配n - 1 项而不是n

【讨论】:

  • 轻微警告:结构的填充/对齐要求将由最严格的元素决定;一个灵活的数组元素,其类型需要比结构中的任何其他内容更严格的对齐方式,因此可能会改变结构的填充和对齐方式。例如,在某些机器上,包含 charfloat[] 的结构可能是 4 个字节并且需要四字节对齐,即使没有 double[] 它也只有一个字节。
【解决方案2】:

expr_t *e = malloc (sizeof (expr_t) + n * sizeof (expr_t *)); 在 C99 中定义良好。来自 C99 规范 6.7.2.1.16:

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

【讨论】:

    猜你喜欢
    • 2012-11-03
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多