Cryptic struct definition in C

人盡茶涼 提交于 2019-12-05 01:20:59
Shafik Yaghmour

This code is using a combination of designated initializers and compound literals, which are both C99 features, I linked to other answer where I provide standard quotes for both of these features.

Designated initializers allow you to use specify a specific field to initialize using .fieldname =, an example from the linked document is:

 struct point { int x, y; };

the following initialization

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

is equivalent to

struct point p = { xvalue, yvalue };

The other feature being used is compound literals which is being used to create unnamed static objects and then the code takes the address of this object and assigns it the respective pointers left and right. It then uses this feature recursively within the unnamed objects to set their respective left and right pointers.

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

These unnamed objects are only static if they are used outside the body of a function otherwise they will have automatic storage duration and would cease to exist once you exit the function and so taking their addresses like the code is doing would probably be unwise.

For reference I provide a standard quote on compound literals in my answer here.

Important to note that when using designated initializers any field not explicitly initialized will be initialized to zero, which is actually important in this case, for example hasCheese will be set to 0 unless it is specifically set otherwise.

Although these are C99 features not all compilers support or fully support C99, my tests on Visual Studio show that we need to replace the empty compound literals, for example:

left = &(maze_t) {}

with a NULL to get it to compile. I filed a bug report.

The response to the bug report was as follows, but basically this is a gcc/clang extension at work:

This is a GNU extension. Clang supports it as an extension (see the clang option -Wgnu-empty-initializer).

The standard way to write this is {0}, which will zero initialize all fields.

The code is initializing a struct according to a syntax allowed in the C since 1999 (C99 and C11).

Briefly explained, you can initialize a struct variable by writting only the "members" of the struct enclosed in braces { }.

For example, given the following struct:

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

we can define and initialize struct variables as follows:

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

As you can see, it's enough to write the members, without the variable-name r.
This syntax is allowed in initializers.

Also, in normal assignments we can have a similar syntax with the aid of compound literals, as in this example:

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

Search on internet about these topics: C struct initializers and C compound literals, to obtain more information (technical note: ANSI C89 doesn't have this syntax, so search for ISO C99 and ISO C11).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!