C型结构中的柔性阵列构件

xt0899hw  于 2023-03-28  发布在  其他
关注(0)|答案(4)|浏览(102)

引用自C-std部分6.7.2.1,

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

这是一个有效的结构声明。我正在寻找这种语法的一些实际用途。确切地说,这种结构比保留双精度 * 作为第二个元素更强大或更不强大?或者这是另一种“你可以用多种方式来做它”的情况?
阿尔潘

ssm49v7z

ssm49v7z1#

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类型的数组必然会在这种情况下变得复杂。
对于你补充的问题“这个结构比保持一个[指针]作为第二个元素更强大还是更不强大?”,它本身并没有更强大,但是你不需要在周围保持指针,所以你至少可以保存那么多空间-而且当你复制结构时,你也会复制数组,而不是指向数组的指针-有时候会有细微的区别,但在其他时候非常重要。“你可以用多种方式来做”可能是一个很好的解释,但也有一些情况下,你会特别想要一个设计或其他。

66bbxpm5

66bbxpm52#

主要优点是灵活的数组成员允许您为数组分配 * 单个 * 内存块沿着结构中的其他数据(使用指针,通常最终会有两个单独分配的块)。
它还适用于通过许多网络协议传输的数据,其中传入流的定义方式相同--一个整数定义长度,后面跟着许多单位(通常为字节/八位字节)。您可以(通常)使用类型双关语将具有灵活数组成员的结构体覆盖到填充有此类数据的缓冲区上,并直接使用它,而不是必须将其解析成片段,然后单独使用这些片段。

8fsztsew

8fsztsew3#

你可以用它来添加头字段到动态分配的数组中,最常见的一个是它的大小:

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

osh3o9ms

osh3o9ms4#

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

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

相关问题