简体   繁体   English

C结构中的柔性阵列构件

[英]Flexible array member in C-structure

Quoting from the C-std section 6.7.2.1, 引自C-std部分6.7.2.1,

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

This is a valid structure declaration. 这是一个有效的结构声明。 I am looking for some practical use of this kind of syntax. 我正在寻找这种语法的一些实际用途。 To be precise, how is this construct any more or less powerful than keeping a double* as the 2nd element? 确切地说,这个构造如何比保持double *作为第二个元素更强或更弱? Or is this another case of 'you-can-do-it-in-multiple-ways'? 或者这是“你可以做多种方式”的另一种情况吗?

Arpan Arpan

The C FAQ answers precisely this question. C FAQ恰好回答了这个问题。 The quick answer is that this structure will include the double array inside the structure rather than a pointer to an array outside the structure. 快速回答是这个结构将在结构内部包含double数组,而不是指向结构外部的数组的指针。 As a quick example, you could use your structure as in this example: 作为一个简单的示例,您可以像在此示例中一样使用您的结构:

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;

And so on - the size of the array you care about is included in the allocation, and then you can use it just like any array. 依此类推 - 你关心的数组的大小包含在分配中,然后就像任何数组一样使用它。 Normally such a type contains the size as part of the structure, since using the + trick to skip through an array of type s will be necessarily complicated by this situation. 通常这样的类型包含作为结构的一部分的大小,因为使用+技巧跳过类型s的数组将必然因此情况而复杂化。

To your added question 'how is this construct any more or less powerful than keeping a [pointer] as the 2nd element?', it's no more powerful per se, but you don't need to keep a pointer around, so you would save at least that much space - also when you are copying the structure, you would also copy the array, rather than a pointer to an array - a subtle difference sometimes, but very important other times. 对于你添加的问题'这个构造如何比将[指针]保持为第二个元素更强或更弱?',它本身不再强大 ,但你不需要保持指针,所以你会节省至少那么多的空间 - 也就是当你复制结构时,你也会复制数组,而不是指向数组的指针 - 有时是微妙的差异,但在其他时候非常重要。 'You-can-do-it-in-multiple-ways' is probably a good explanation, but there are cases where you would specifically want one design or the other. “你可以用多种方式做”可能是一个很好的解释,但有些情况下你会特别想要一个设计或另一个。

The primary advantage is that a flexible array member allows you to allocate a single block of memory for the array along with the other data in the struct (with a pointer, you'd typically end up with two separately allocated blocks). 主要优点是灵活的数组成员允许您为数组分配单个内存块以及结构中的其他数据(使用指针,您通常最终会得到两个单独分配的块)。

It's also useful with data transmitted by quite a few network protocols, where the incoming stream is defined the same way -- an integer defining a length, followed by that many units (typically bytes/octets) of data. 它对于通过相当多的网络协议传输的数据也很有用,其中输入流以相同的方式定义 - 定义长度的整数,接着是许多单元(通常是字节/八位字节)的数据。 You can (typically) use a type-pun to overlay a struct with a flexible array member onto a buffer filled with such data, and work with it directly instead of having to parse it out into pieces and then work with the pieces individually. 您可以(通常)使用类型双关语将具有灵活数组成员的结构覆盖到填充有此类数据的缓冲区上,并直接使用它而不必将其解析成片段,然后单独处理这些片段。

You can use it to add header fields to dynamically allocated arrays, the most common one of which would be its size: 您可以使用它将头字段添加到动态分配的数组中,其中最常见的是其大小:

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;

You could achieve similar results by using an int * member instead and allocating the array seperately, but it would be less efficient both in terms of memory (additional pointer, heap management for 2nd memory block) and runtime (additional indirection, 2nd allocation). 您可以通过使用int *成员而单独分配数组来实现类似的结果,但在内存(附加指针,第二内存块的堆管理)和运行时(附加间接,第二次分配)方面效率都会降低。

I've seen this used on Windows for strings which are tagged by their length. 我已经在Windows上看到过用于标记长度的字符串的字符串。 The character data is stored directly after the length in memory, keeping everything together neatly. 字符数据直接存储在内存中,将所有内容整齐地保存在一起。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM