简体   繁体   English

C 中是否有静态初始化灵活数组成员的标准方法?

[英]Is there a standard way to statically initialize flexible array members in C?

I need a statically created data structure in memory comprised of a table of string vectors, effectively:我需要在 memory 中静态创建的数据结构,该结构由字符串向量表组成,有效地:

typedef struct {
    char *argv[];
} Entry;

const Entry Table[] = {
    {"a"},
    {"a", "b", "c"}
};

But trying to compile this results in error: initialization of flexible array member in a nested context但是尝试编译它会导致error: initialization of flexible array member in a nested context

Apparently this is possible in GCC, according GCC Manual: 6.18 Arrays of Length Zero .显然,这在 GCC 中是可能的,根据GCC Manual: 6.18 Arrays of Length Zero This may be possible following C 2018 6.7.2.1 18, although in regard to that I read elsewhere在 C 2018 6.7.2.1 18 之后,这可能是可能的,尽管关于我在其他地方读到的

There cannot be an array of structures that contain a flexible array member.不能有包含灵活数组成员的结构数组。

Is there a standard way to achieve this behavior?有没有标准的方法来实现这种行为? If not, is there a preferred way?如果没有,是否有首选方法?

You can't do it with a flexible array member.你不能用灵活的数组成员来做到这一点。

Instead, you can use char **argv and initialize it using compound literals.相反,您可以使用char **argv并使用复合文字对其进行初始化。

typedef struct {
    char **argv;
} Entry;

const Entry table[] = {
    { (char *[]) { "a", NULL } },
    { (char *[]) { "a", "b", "c", NULL } }
};

I added NULL to each of the arrays so the application can tell their lengths (the real argv has this as well).我将NULL添加到 arrays 中的每一个,这样应用程序就可以知道它们的长度(真正的argv也有这个)。

You do not store the count of elements of argv.您不存储 argv 的元素计数。 How would you know that the first one has 1 element, and the second one has 3?你怎么知道第一个有 1 个元素,第二个有 3 个元素? You have to store that, for example, in another array member.例如,您必须将其存储在另一个数组成员中。

You can define a structure that has the proper exact same static memory layout as the array of structures with flexible array members that you want to have.您可以定义一个结构,该结构具有与您想要的具有灵活数组成员的结构数组完全相同的 static memory 布局。 Then you can then alias the structure with a pointer to Entry , and use that as an array of entries.然后,您可以使用指向Entry的指针为结构命名,并将其用作条目数组。 Following example does that:下面的例子是这样做的:

#include <stdlib.h>
#include <assert.h>
#include <stdalign.h>
#include <stddef.h>
#include <stdio.h>

typedef struct {
    unsigned len;
    char *argv[];
} Entry;

// sane iterating
static_assert(alignof(Entry) == alignof(char *), "");

typedef struct {
    unsigned len;
    char *argv[1];
} Entry_1;
static_assert(alignof(Entry_1) == alignof(Entry), "");
static_assert(sizeof(Entry_1) == sizeof(Entry) + 1 * sizeof(char *), "");

typedef struct {
    unsigned len;
    char *argv[3];
} Entry_3;
static_assert(alignof(Entry_3) == alignof(Entry), "");
static_assert(sizeof(Entry_3) == sizeof(Entry) + 3 * sizeof(char *), "");

typedef struct {
    Entry_1 e1;
    Entry_3 e3;
} Entry_init_1_3;
static_assert(offsetof(Entry_init_1_3, e3) == sizeof(Entry_1), "");

const Entry_init_1_3 entry_init_1_3 = {
    { 1, { "a", } },
    { 3, { "b", "c", "d", } },
};

const Entry *const table = (const void *)&entry_init_1_3;
//                         ^^^^^^^^^^^^^^^ I hope I know what I am doing.
const Entry *const table_end = (const Entry*)((const char*)table + sizeof(entry_init_1_3));

const Entry *table_next(const Entry *it) {
    return (const Entry *)(
        (const char *)it + sizeof(Entry) + it->len * sizeof(char *)
    );
}

int main() {
    unsigned entry_idx = 0;
    for (const Entry *it = table;
            it != table_end;
            it = table_next(it), ++entry_idx
    ) {
        for (unsigned x = 0; x < it->len; ++x) {
            fprintf(stderr, "table[%d].argv[%d] = %s\n",
                entry_idx,
                x,
                it->argv[x]
            );
       }
    }
}

Code outputs:代码输出:

table[0].argv[0] = a
table[1].argv[0] = b
table[1].argv[1] = c
table[1].argv[2] = d

Most notable inotify() Linux system call returns an array of flexible array members.最著名的inotify() Linux 系统调用返回一个灵活的数组成员数组。

Is there a standard way to statically initialize flexible array members in C? C 中是否有静态初始化灵活数组成员的标准方法?

No.不。

If not, is there a preferred way?如果没有,是否有首选方法?

Don't use flexible array members.不要使用灵活的数组成员。 Use pointers, as presented in the other answer.使用其他答案中介绍的指针。

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

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