C结构中的柔性阵列构件

时间:2010-06-15 17:33:34

标签: c c99 flexible-array-member

引自C-std部分6.7.2.1,

struct s { int n; double d[]; };

这是一个有效的结构声明。我正在寻找这种语法的一些实际用途。确切地说,这个构造如何比保持double *作为第二个元素更强或更弱?或者这是“你可以做多种方式”的另一种情况吗?

Arpan

4 个答案:

答案 0 :(得分:10)

C FAQ恰好回答了这个问题。快速回答是这个结构将在结构中包含double数组,而不是指向结构外部的数组的指针。作为一个简单示例,您可以使用您的结构,如下例所示:

struct s mystruct = malloc(sizeof(struct s) + 5 * sizeof(double));
s.n = 12;
s.d[0] = 4.0;
s.d[1] = 5.0;
s.d[2] = 6.0;
s.d[3] = 7.0;
s.d[4] = 8.0;

依此类推 - 你关心的数组的大小包含在分配中,然后就像任何数组一样使用它。通常这样的类型包含作为结构一部分的大小,因为使用+技巧跳过类型s的数组将因此而变得复杂。

对于你添加的问题'这个构造如何比将[指针]保持为第二个元素更强或更弱?',它不再是强大的本身,但你不需要保持一个指针,所以你至少可以节省那么多空间 - 当你复制结构时,你也会复制数组,而不是指向数组的指针 - 有时是微妙的差异,但其他时候非常重要。 “你可以做多种方式”可能是一个很好的解释,但有些情况下你会特别想要一个设计或另一个。

答案 1 :(得分:4)

主要优点是灵活的数组成员允许您为数组分配单个内存块以及结构中的其他数据(使用指针,您通常会结束有两个单独分配的块)。

它对于通过相当多的网络协议传输的数据也很有用,其中传入流以相同的方式定义 - 定义长度的整数,然后是数据的许多单位(通常是字节/八位字节)。您可以(通常)使用类型双关语将具有灵活数组成员的结构覆盖到填充有此类数据的缓冲区上,并直接使用它而不必将其解析为多个部分,然后单独处理这些部分。 / p>

答案 2 :(得分:2)

您可以使用它将标题字段添加到动态分配的数组中,其中最常见的是其大小:

struct int_array
{
    size_t size;
    int values[];
};

struct int_array *foo = malloc(sizeof *foo + 42 * sizeof *foo->values);
foo->size = 42;

...

for(size_t i = 0; i < foo->size; ++i)
    foo->values[i] = i * i;

您可以通过使用int *成员并分别分配数组来获得类似的结果,但在内存(附加指针,第二个内存块的堆管理)和运行时(附加)方面效率都会降低间接,第二次分配)。

答案 3 :(得分:0)

我在Windows上看到过这个用于标记长度的字符串的字符串。字符数据直接存储在内存中,将所有内容整齐地保存在一起。

typedef struct {
    SIZE_T bytes;
    TCHAR chars[];
} tagged_string;