嵌套数组的初始化?

时间:2018-10-07 15:36:02

标签: c arrays struct initialization

我要转换此Python代码:

outsides = [
    {   'baz': 7,
        'foobar': [   {'bar': 2, 'foo': 1},
                      {'bar': 4, 'foo': 3},
                      {'bar': 6, 'foo': 5}]},
    {'baz': 8}]

对C。到目前为止,我想到了以下代码:

#include <stdio.h>

struct Inside {
    int foo;
    int bar;
};

struct Outside {
    int baz;
    const struct Inside* foobar;
};

const struct Inside insides[] = {
    { .foo = 1, .bar = 2 },
    { .foo = 3, .bar = 4 },
    { .foo = 5, .bar = 6 },
};

const struct Outside outsides[] = {
    { .baz = 7, .foobar = insides },
    { .baz = 8, .foobar = NULL },
};

int main(int argc, char *argv[])
{
    printf("outsides: %i\n", sizeof(outsides) / sizeof(Outside));
    printf("insides: %i\n", sizeof(outsides[0].foobar));
    return 0;
}

但是有两个问题:

  1. 如何在外部声明中内联内部声明?
  2. 如何确定foobar成员的内部元素数量?

对于问题2,我可以实现一些解决方法,例如使用0初始化最后一个元素,然后对其进行循环并测试所有0,或者在Outside结构中添加一个额外的count成员,但这看起来并不正确。完美的是,如果还有另一个间接方式:如果foobar成员是一个指向Inside元素的指针数组,那么我可以在末尾添加一个空指针。

注意:这是一个简化的示例,它演示了我有两个基本问题,但是我不能使用一个灵活的数组成员,因为在Outside结构中有多个灵活的数组成员。当然,foobar成员的对象数量可以变化。而且我需要一个适用于C而不是C ++的解决方案。

1 个答案:

答案 0 :(得分:3)

要回答问题1,因为您已经指定了初始化程序,所以您也有compound literals。但是,要回答问题2,您必须告诉代码指针所指向的数组中有多少个条目。 C不会为您记录信息。您可以使用标记值,也可以显式记录计数。无论哪种方式,您都必须这样做。 C不会为您做任何幕后工作。而且,尽管您可以将struct Inside的定义嵌套在struct Outside内,但是没有像C ++那样进行范围界定,以防止您独立于struct Inside使用struct Outside,因此这样做没有任何好处。 —就像您一样,我将结构定义分开。

因此,您可以使用:

struct Inside
{
    int foo;
    int bar;
};

struct Outside
{
    int baz;
    size_t num_foobar;
    const struct Inside* foobar;
};    

const struct Outside outsides[] =
{
    { .baz = 7, .num_foobar = 3,
      .foobar = (struct Inside[]){
                    { .foo = 1, .bar = 2 },
                    { .foo = 3, .bar = 4 },
                    { .foo = 5, .bar = 6 },
      }
    },
    { .baz = 8, .num_foobar = 0, .foobar = NULL },
};

最后一个.num_foobar = 0可以省略,因为未指定的成员无论如何都初始化为零,但是我不建议这样做。如果愿意,可以使用int代替size_t。 (上面的代码需要<stddef.h>或定义size_t的其他头文件之一(例如<stdio.h>)–但添加了#include <stddef.h>后,它为我干净地编译为目标代码)

我错过了您的请求:

  

如果还有另一个间接方式,那将是完美的:如果foobar成员是指向Inside元素的指针数组,那么我可以在末尾添加一个空指针。

这可以通过结构中的类型更改和初始化程序中的更多工作来完成。我认为上面的代码相当容易理解,但是下面的代码也不是完全可怕的。

#include <stddef.h>

struct Inside
{
    int foo;
    int bar;
};

struct Outside
{
    int baz;
    const struct Inside **foobar;
};    

const struct Outside outsides[] =
{
    { .baz = 7,
      .foobar = &((const struct Inside*[]){
                    &(struct Inside){ .foo = 1, .bar = 2 },
                    &(struct Inside){ .foo = 3, .bar = 4 },
                    &(struct Inside){ .foo = 5, .bar = 6 },
                    NULL,
                })[0],
    },
    { .baz = 8, .foobar = NULL },
};

虽然这是“可行的”,但我绝对喜欢第一个代码。