灵活arrays成员的真正好处是什么?

在阅读了一些与柔性arrays成员相关的post后,我仍然不完全理解为什么我们需要这样的function。

可能重复:
C中的灵活arrays成员 – 糟糕吗?
这是C中的Flexible Array Struct成员吗?

(如果我没有从上面可能的重复问题中解决我的问题,请怪我)

以下两个实现之间的真正区别是什么:

struct h1 { size_t len; unsigned char *data; }; struct h2 { size_t len; unsigned char data[]; }; 

我知道h2的大小就好像省略了灵活的数组成员(数据),即sizeof(h2) == sizeof(size_t) 。 而且我也知道灵活的数组成员只能作为结构的最后一个元素出现,因此原始实现在data位置可以更灵活。

我真正的问题是为什么C99添加此function? 仅仅因为sizeof(h2)不包含实际大小的数据? 我相信我必须错过这个function的一些更重要的观点。 请指出给我。

你post中的两个结构根本没有相同的结构。 h1有一个整数和一个指向char的指针。 h2有一个整数和一个内联字符数组(在运行时确定的元素数,可能没有)。

换句话说,在h2 ,字符数据在结构内部。 在h1它必须在外面的某个地方。

这有很大的不同。 例如,如果使用h1 ,则需要注意分配/释放有效负载(除了结构本身)。 对于h2 ,只需要一个分配/免费,所有内容都打包在一起。

使用h2可能有意义的一种情况是,如果您正在与期望以{length,data}对forms的消息进行通信。 你通过请求sizeof(h2)+how many payload chars you want分配一个h2实例,填充它,然后你可以在一次write转移整个事物(当然要注意endianess)。 如果您使用过h1 ,则需要两次write调用(除非您想发送数据的内存地址,这通常没有任何意义)。

所以这个function的存在是因为它很方便。 以及之前用于模拟此function的各种(有时是非便携式)技巧。 将其添加到标准中是有道理的。

委员会引入灵活数组成员的主要原因是实现着名的struct hack 。 请参阅C99基本原理的以下引用,特别是我添加重点的部分。

国际标准的基本原理 – 编程语言 – C§6.7.2.1结构和联合说明符

有一个常见的习语称为“struct hack”,用于创建包含可变大小数组的结构:

 struct s { int n_items; /* possibly other fields */ int items[1]; }; struct s *p; size_t n, i; /* code that sets n omitted */ p = malloc(sizeof(struct s) + (n - 1) * sizeof(int)); /* code to check for failure omitted */ p->n_items = n; /* example usage */ for (i = 0; i < p->n_items; i++) p->items[i] = i; 

这种结构的有效性一直是值得怀疑的。 在对一个缺陷报告的回复中,委员会认为它是未定义的行为,因为数组p->items只包含一个项目,无论该空间是否存在。 建议使用替代构造:使数组大小大于最大可能情况(例如,使用int items[INT_MAX]; ),但由于其他原因,此方法也未定义。

委员会认为,虽然没有办法在C89中实施“结构黑客”,但它仍然是一个有用的设施。 因此,引入了“柔性arrays成员”的新特征。 除了空括号,以及在malloc调用中删除“-1” ,它的使用方式与struct hack相同,但现在是明确有效的代码。

灵活的数组成员有一些限制,可以确保使用它们的代码有意义。 例如,必须至少有一个其他成员,并且灵活数组必须最后出现。 类似地,包含灵活数组的结构不能出现在其他结构或数组中。 最后,应用于结构的sizeof忽略数组,但在它之前计算任何填充。 这使得malloc调用尽可能简单。

我不知道这是否被认为是重要的一点,但GCC文件指出了这一点:

GCC允许灵活的arrays成员的静态初始化。 这相当于定义一个包含原始结构的新结构,后跟一个足够大小的数组来包含数据。 例如,在下文中,f1被构造为好像它被声明为f2。

 struct f1 { int x; int y[]; } f1 = { 1, { 2, 3, 4 } }; struct f2 { struct f1 f1; int data[3]; } f2 = { { 1 }, { 2, 3, 4 } }; 

(摘自http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html )