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



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

typedef struct {
char *argv[];
} Entry;
const Entry Table[] = {
{"a"},
{"a", "b", "c"}
};

但是试图编译这个结果是error: initialization of flexible array member in a nested context

显然这在GCC中是可能的,根据GCC手册:6.18长度为零的数组。这可能在C 2018 6.7.2.1 18之后实现,尽管我在其他地方读到

结构体数组不能包含灵活数组成员

是否有一个标准的方法来实现这个行为?如果没有,是否有首选的方法?

你不能在一个灵活的数组成员中这样做。

相反,您可以使用char **argv并使用复合字面值初始化它。
typedef struct {
char **argv;
} Entry;
const Entry table[] = {
{ (char *[]) { "a", NULL } },
{ (char *[]) { "a", "b", "c", NULL } }
};

我将NULL添加到每个数组中,以便应用程序可以告诉它们的长度(真正的argv也具有此功能)。

不存储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] = %sn",
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?

如果没有,是否有更好的方法?

不要使用灵活数组成员。如另一个答案所示,使用指针。

相关内容

  • 没有找到相关文章

最新更新