10

我遇到了以下迷宫定义代码:

typedef struct mazeNode {
    int hasCheese;
    int tag;
    struct mazeNode *left;
    struct mazeNode *right;
} maze_t;

maze_t maze = {
    .tag = 1,
    .left = &(maze_t) {
        .left = &(maze_t) {
            .left = &(maze_t) {},
            .right = &(maze_t) {}
        },
        .right = &(maze_t) {
            .right = &(maze_t) {}
        }
    },
    .right = &(maze_t) {
        .tag = 8,
        .left = &(maze_t) {},
        .right = &(maze_t) {
            .tag = 10,
            .left = &(maze_t) {
                .tag = 11,
                .left = &(maze_t) {
                    .hasCheese = 1,
                    .tag = 12
                }
            },
            .right = &(maze_t) {}
        }
    }
};

从链接的博客文章中,我了解到他们正在尝试用图中的奶酪定义二叉树。

但是,我似乎无法从 C 代码应该做的事情中脱颖而出。如果有人可以向我解释,那就太好了。

4

2 回答 2

10

此代码使用指定初始化程序复合文字的组合,它们都是C99 功能,我链接到其他答案,其中我为这两个功能提供标准引号。

指定初始化器允许您使用指定特定字段进行初始化.fieldname =,链接文档中的一个示例是:

 struct point { int x, y; };

以下初始化

struct point p = { .y = yvalue, .x = xvalue };

相当于

struct point p = { xvalue, yvalue };

正在使用的另一个功能是复合文字,它用于创建未命名的静态对象,然后代码获取该对象的地址并为其分配相应的指针leftright. 然后它在未命名的对象中递归地使用此功能来设置它们各自的left指针right

 .left = & (maze_t) { .... }
           ^^^^^^^^^^^^^^^^
           unnamed static object

这些未命名的对象只有在函数体之外使用时才是静态的,否则它们将具有自动存储持续时间并且一旦退出函数就会不复存在,因此像代码那样获取它们的地址可能是不明智的。

作为参考,我在此处的回答中提供了关于复合文字的标准报价。

需要注意的是,当使用指定的初始化器时,任何未显式初始化的字段都将被初始化为零,这在这种情况下实际上很重要,例如hasCheese将设置为,0除非另有明确设置。

尽管这些是 C99 功能,并非所有编译器都支持或完全支持 C99,但我在Visual Studio上的测试表明我们需要替换空的复合文字,例如:

left = &(maze_t) {}

用 aNULL让它编译。我提交了错误报告

对错误报告的响应如下,但基本上这是一个 gcc/clang 扩展在工作:

这是一个 GNU 扩展。Clang 支持它作为扩展(参见 clang 选项 -Wgnu-empty-initializer)。

编写它的标准方法是 {0},它将对所有字段进行零初始化。

于 2014-08-30T01:43:02.200 回答
3

代码根据自 1999 年以来 C 语言中允许的语法(C99 和 C11)初始化结构。

简而言之,您可以通过仅写入大括号 {} 中的结构的“成员”来初始化结构变量。

例如,给定以下结构:

 struct fractional_number_s { int numerator; unsigned int denominator; };

我们可以如下定义和初始化结构变量:

 struct fractional_number_s r = { .numerator = 3, .denominator = 7, };  

如您所见,编写成员就足够了,没有变量名r
初始化器中允许使用此语法。

此外,在普通赋值中,我们可以借助复合文字获得类似的语法,如下例所示:

 r = (struct fractional_numbers_s) { .numerator = 3, .denominator = 7 };  

在 Internet 上搜索以下主题:C struct initializersC Compound literals,以获取更多信息(技术说明: ANSI C89 没有此语法,因此请搜索 ISO C99 和 ISO C11)。

于 2014-08-30T01:48:09.587 回答