C 结构中的灵活数组成员

发布于 2024-09-05 09:09:08 字数 197 浏览 4 评论 0原文

引用 C-std 第 6.7.2.1 节,

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

这是一个有效的结构声明。我正在寻找这种语法的一些实际用途。准确地说,这个构造与将 double* 作为第二个元素相比有何不同?或者这是“你可以用多种方式做到这一点”的另一种情况?

阿尔潘

Quoting from the C-std section 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? Or is this another case of 'you-can-do-it-in-multiple-ways'?

Arpan

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

○闲身 2024-09-12 09:09:08

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 类型的数组在这种情况下必然会变得复杂。

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

The C FAQ answers precisely this question. 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. 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;

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.

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.

尝蛊 2024-09-12 09:09:08

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

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

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.

活泼老夫 2024-09-12 09:09:08

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

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 * 成员并单独分配数组来实现类似的结果,但是在内存(附加指针、第二个内存块的堆管理)和运行时(附加间接、第二次分配)方面,它的效率都会较低。

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).

百善笑为先 2024-09-12 09:09:08

我见过它在 Windows 上用于按长度标记的字符串。字符数据直接存储在内存中的长度之后,使所有内容整齐地排列在一起。

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

I've seen this used on Windows for strings which are tagged by their length. The character data is stored directly after the length in memory, keeping everything together neatly.

typedef struct {
    SIZE_T bytes;
    TCHAR chars[];
} tagged_string;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文