如果您只打算移植到支持 C99 的机器(编译器),那么您可以考虑使用“灵活数组成员”,它是“struct hack”的可移植版本。
§6.7.2.1 结构和联合说明符
¶16 作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能
数组类型不完整;这称为灵活数组成员。有两个
例外,灵活的数组成员被忽略。首先,结构的尺寸应为
等于替换的相同结构的最后一个元素的偏移量
具有未指定长度的数组的灵活数组成员。106) 其次,当.(或->)
运算符的左操作数是(指向)具有灵活数组成员的结构
并且正确的操作数命名该成员,它的行为就像该成员被替换
具有不会构成结构的最长数组(具有相同元素类型)
大于被访问的对象;数组的偏移量应保持在
灵活的数组成员,即使这与替换数组的不同。如果这
数组将没有元素,它的行为就像它只有一个元素,但行为是
如果尝试访问该元素或在过去生成一个指针,则未定义
它。
¶17 示例假设所有数组成员在声明之后对齐相同:
struct s { int n; double d[]; };
struct ss { int n; double d[1]; };
三种表达方式:
sizeof (struct s)
offsetof(struct s, d)
offsetof(struct ss, d)
具有相同的值。结构体struct s 有一个灵活的数组成员d。
106) 未指定长度以允许实现可能给数组成员不同的事实
根据长度对齐。
在上下文中,这意味着你可以写:
typedef struct mystruct
{
int x;
struct y *list[];
} mystruct; // Note that this is necessary; C++ automatically recognizes mystruct; C does not.
要分配空间,您可以使用:
mystruct *h1 = (mystruct *)malloc(sizeof(mystruct) + 10 * sizeof(struct y *));
这会分配一个mystruct,并为数组中的 10 个指针分配足够的空间。您可以稍后调整内存大小:
mystruct *new_h1 = (mystruct *)realloc(h1, sizeof(mystruct) + 20 * sizeof(struct y *));
if (new_h1 == 0)
...handle out of memory error, but note that h1 is still valid...
h1 = new_h1; // Safe
(请注意,我在重新分配时小心不要分配给h1;如果您遇到内存分配失败,这样做会泄漏内存。)
您可以像数组一样引用它们:
h1->list[0] = ...;
请注意,您不能拥有mystruct 的数组,但可以拥有指向mystruct 的指针数组。您还可以密切关注数组的大小;你通常会做一些事情,比如让一个固定成员记录分配的大小。