[英]Cryptic struct definition in C
我遇到了以下迷宫定义代码:
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代码应该做的事情。 如果有人能向我解释它会很棒。
此代码使用指定的初始化程序和复合文字的组合,这两者都是C99功能 ,我链接到其他答案,我为这两个功能提供标准报价。
指定的初始值设定项允许您使用.fieldname =
指定特定字段进行初始化,链接文档中的示例如下:
struct point { int x, y; };
以下初始化
struct point p = { .y = yvalue, .x = xvalue };
相当于
struct point p = { xvalue, yvalue };
所使用的其他特征是,其是被用来创建无名静态对象复合文字,然后将代码借此对象的地址和分配给它的相应指针left
和right
。 然后,它使用此功能递归无名对象中设置各自的left
和right
指针。
.left = & (maze_t) { .... }
^^^^^^^^^^^^^^^^
unnamed static object
这些未命名的对象只有在函数体外使用时才是静态的,否则它们将具有自动存储持续时间,并且一旦退出函数就会停止存在,因此像代码那样获取它们的地址可能是不明智的。
作为参考,我在这里提供了关于复合文字的标准引用。
需要注意的是,当使用指定的初始化程序时,任何未明确初始化的字段都将初始化为零 ,这在这种情况下实际上很重要,例如hasCheese
将设置为0
除非另有特别设置。
虽然这些是C99功能并非所有编译器都支持或完全支持C99,但我对Visual Studio的测试表明我们需要替换空的复合文字,例如:
left = &(maze_t) {}
用NULL
来编译它。 我提交了一份错误报告 。
对bug报告的响应如下,但基本上这是一个gcc / clang扩展工作:
这是一个GNU扩展。 Clang支持它作为扩展(参见clang选项-Wgnu-empty-initializer)。
写这个的标准方法是{0},它将零初始化所有字段。
该代码根据自1999年以来C中允许的语法初始化结构(C99和C11)。
简要说明,您可以通过仅写入括号{}中包含的结构的“成员”来初始化结构变量。
例如,给定以下结构:
struct fractional_number_s { int numerator; unsigned int denominator; };
我们可以定义和初始化struct变量,如下所示:
struct fractional_number_s r = { .numerator = 3, .denominator = 7, };
正如您所看到的,编写成员就足够了,而没有变量名r
。
初始值设定项中允许使用此语法。
此外,在正常分配中,我们可以在复合文字的帮助下使用类似的语法,如下例所示:
r = (struct fractional_numbers_s) { .numerator = 3, .denominator = 7 };
在互联网上搜索这些主题: C struct initializers和C compound literals ,以获取更多信息( 技术说明: ANSI C89没有此语法,因此搜索ISO C99和ISO C11)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.