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代码应该做的事情。 如果有人能向我解释它会很棒。
此代码使用指定的初始化程序和复合文字的组合,这两者都是C99function ,我链接到其他答案,我为这两个function提供标准报价。
指定的初始值设定项允许您使用.fieldname =
指定特定字段进行初始化,链接文档中的示例如下:
struct point { int x, y; };
以下初始化
struct point p = { .y = yvalue, .x = xvalue };
相当于
struct point p = { xvalue, yvalue };
正在使用的另一个特性是复合文字,它用于创建未命名的静态对象,然后代码获取该对象的地址并为其分配left
各自的指针。 然后,它在未命名的对象中递归地使用此function来设置它们各自的right
指针。
.left = & (maze_t) { .... } ^^^^^^^^^^^^^^^^ unnamed static object
这些未命名的对象只有在函数体外使用时才是静态的,否则它们将具有自动存储持续时间,并且一旦退出函数就会停止存在,因此像代码那样获取它们的地址可能是不明智的。
作为参考,我在这里提供了关于复合文字的标准引用。
需要注意的是,当使用指定的初始值设定项时,任何未明确初始化的字段都将初始化为零 ,这在这种情况下实际上很重要,例如hasCheese
将设置为0
除非另有特别设置。
虽然这些是C99function并非所有编译器都支持或完全支持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)。