如何初始化这个结构体数组的数组的结构体?

4
我有以下代码,但它并没有按照预期工作。它可以编译,但在执行时会抛出很多警告和段错误:
#include <stdio.h>

enum output {
    A,
    B,
    C,
    D,
};

struct translation {
    char *from;
    enum output to;
};

struct dictionary {
    struct translation *foo;
    struct translation *bar;
};

enum language {
    ONE,
    ANOTHER,
};

struct dictionary languages[] = {
        [ONE] = {
                .foo = {
                        {"LF", A},
                        {"LLF", C},
                        {"RRF", D},
                },
                .bar = {
                        {"L", B},
                },
        },
        [ANOTHER] = {
                .foo = {
                        {"FF", B},
                        {"RRF", D},
                },
                .bar = {
                        {"LF", B},
                        {"R", C},
                        {"RR", D},
                },
        },
};

int main(void)
{
        printf("%s\n", languages[ONE].foo[0].from);
        return 0;
}

我可能以错误的方式初始化了languages

  • 我想要一个languages数组,其中我可以通过language访问不同的字典:languages [ONE]
  • 我想要使用字典字段访问不同的翻译表格:languages [ONE] .foo
  • 所有通过语言+字段对访问的翻译表格可能具有不同的数组长度,如代码示例所示

这可行吗?我做错了什么?

使用gcc编译时,我会得到以下(裁剪后的)输出:

asdf.c:27:17: warning: braces around scalar initializer
                 .foo = {
                 ^
asdf.c:27:17: note: (near initialization for ‘languages[0].foo’)
asdf.c:28:25: warning: braces around scalar initializer
                         {"LF", A},
                         ^
asdf.c:28:25: note: (near initialization for ‘languages[0].foo’)
asdf.c:28:26: warning: initialization of ‘struct translation *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types]

[...]

代码的多个部分都有相同的警告/注释。


@FiddlingBits,实际上,那可能是一个解决方法! :-) 我尝试使用[](没有大小),但那是非法的。如果你愿意,你可以把它发表为答案。虽然在接受之前,我会等待看看是否有一种方法可以使这个工作而不必指定一个足够大以容纳所有翻译的字典表大小。 - Peque
2个回答

3

以下是两种方法:

  1. struct translation *foo;struct translation *bar; 分配内存(也可以使用 malloc 动态分配内存)。例如:
struct dictionary
{
    struct translation foo[10];
    struct translation bar[10];
};
  1. 在定义中使用复合字面量:
struct dictionary languages[] = {
    [ONE] = {
            .foo = (struct translation []){
                    {"LF", A},
                    {"LLF", C},
                    {"RRF", D},
            },
            .bar = (struct translation []){
                    {"L", B},
            },
    },
    [ANOTHER] = {
            .foo = (struct translation []){
                    {"FF", B},
                    {"RRF", D},
            },
            .bar = (struct translation []){
                    {"LF", B},
                    {"R", C},
                    {"RR", D},
            },
    },
};

注意

正如@M.M所提到的,如果在运行时其值不会改变,那么在struct dictionary之前添加限定符const是一个好主意。


1
喜欢后者 <3。我通过这个项目学到了很多C语言。 :-D - Peque
使用类似 struct translation foo[10]; 这样的代码(其中一些变量未初始化)是一个非常糟糕的想法,而复合字面量则是 C99 语言的一个特性。 - user7860670
我想添加一条注释,除非您打算在运行时修改它们,否则这些都应该是“const”。 - M.M
1
@VTT 不一定;在某些系统中,内存很便宜,而其他问题,例如代码清晰度、可移植性、开发便利性、运行时访问便利性等可能具有更高的优先级。 - M.M
@M.M 代码的清晰度、开发的便利性(这一点不适用于C语言)、运行时访问的便利性都会受到影响。即使有一个解释说“10应该足够了”。 - user7860670
显示剩余4条评论

1

只需分别初始化每个数组:

#include <stdio.h>

enum output
{
    a
,   b
,   c
,   d
};

struct translation
{
    char const * from;
    enum output  to;
};

struct dictionary
{
    struct translation * foo;
    struct translation * bar;
};

enum language
{
    one
,   another
,   languages_count
};

struct translation one_language_foo_translations[] =
{
    {"LF" , a}
,   {"LLF", c}
,   {"RRF", d}
};

struct translation one_language_bar_translations[] =
{
    {"L", b}
};

struct translation another_language_foo_translations[] =
{
    {"FF" , b}
,   {"RRF", d}
};

struct translation another_language_bar_translations[] =
{
    {"LF", b}
,   {"R" , c}
,   {"RR", d}
};

struct dictionary languages[languages_count] =
{
    {one_language_foo_translations, one_language_bar_translations}
,   {another_language_foo_translations, another_language_bar_translations}
};

int main(void)
{
    printf("%s\n", languages[one].foo[0].from);
    return 0;
}

在线编译器


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接