C结构中的柔性阵列构件

Fan*_*c23 5 c c99 flexible-array-member

引自C-std部分6.7.2.1,

struct s { int n; double d[]; };
Run Code Online (Sandbox Code Playgroud)

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

Arpan

Car*_*rum 10

Ç常见问题的答案正是这个问题.快速回答是这个结构将包括结构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;
Run Code Online (Sandbox Code Playgroud)

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

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


Chr*_*oph 5

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

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;
Run Code Online (Sandbox Code Playgroud)

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


Jer*_*fin 5

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

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