这些是所谓的“struct hack”的各种形式,在comp.lang.c FAQ的问题 2.6 中进行了讨论。
在 C 中定义大小为 0 的数组实际上是非法的,并且至少从 1989 年 ANSI 标准开始就是这样。一些编译器允许它作为扩展,但依赖它会导致代码不可移植。
实现这一点的一种更便携的方法是使用长度为 1 的数组,例如:
struct foo {
size_t len;
char str[1];
};
您可以分配多个sizeof (struct foo)
字节,len
用于跟踪分配的大小,然后访问str[N]
以获取数组的第 N 个元素。由于 C 编译器通常不进行数组边界检查,这通常会“工作”。但是,严格来说,行为是未定义的。
1999 年的 ISO 标准添加了一个称为“灵活数组成员”的功能,旨在取代这种用法:
struct foo {
size_t len;
char str[];
};
您可以使用与旧的 struct hack 相同的方式来处理这些问题,但行为是明确定义的。但是你必须自己做所有的簿记;sizeof (struct foo)
例如,仍然不包括数组的大小。
当然,您可以改用指针:
struct bar {
size_t len;
char *ptr;
};
这是一个非常好的方法,但它有不同的语义。“struct hack”或灵活数组成员的主要优点是数组与结构的其余部分连续分配,并且您可以使用memcpy
(只要目标正确分配)。使用指针,数组是单独分配的——这可能是也可能不是你想要的。