在C语言中有没有静态初始化灵活数组成员的标准方法?

avwztpqn  于 2023-01-08  发布在  其他
关注(0)|答案(2)|浏览(232)

我需要在内存中静态创建一个由字符串向量表组成的数据结构,有效地:

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

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

但是尝试编译这个结果是error: initialization of flexible array member in a nested context
显然,根据GCC Manual: 6.18 Arrays of Length Zero,这在GCC中是可能的。在C 2018 www.example.com 18之后,这可能是可能6.7.2.1的,尽管我在其他地方读到过
不能存在包含灵活数组成员的结构数组。
是否有一个标准的方法来实现这种行为?如果没有,是否有一个 * 首选 * 的方法?

b09cbbtk

b09cbbtk1#

您无法使用灵活的数组成员执行此操作。
相反,您可以使用char **argv,并使用复合文本对其进行初始化。

typedef struct {
    char **argv;
} Entry;

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

我向每个数组添加了NULL,这样应用程序就可以知道它们的长度(真实的的argv也有这个)。

hkmswyz6

hkmswyz62#

你没有存储argv的元素计数,你怎么知道第一个有1个元素,第二个有3个元素?你必须存储它,例如,在另一个数组成员中。
您可以定义一个结构,它具有与您想要的具有灵活数组成员的结构数组完全相同的静态内存布局。然后,您可以使用指向Entry的指针为该结构指定别名,并将其用作条目数组。以下示例完成了此操作:

#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]
            );
       }
    }
}

代码输出:

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

最值得注意的inotify() Linux系统调用返回一个由灵活数组成员组成的数组。
在C语言中有没有静态初始化灵活数组成员的标准方法?
没有。
如果没有,是否有更好的办法?
不要使用灵活的数组成员,使用指针,如另一个答案所示。

相关问题