static struct fuse_oprations hello_oper = {
.getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
};
I don't understand this C syntax well. I can't even search because I don't know the syntax's name. What's that?
This is a C99 feature that allows you to set specific fields of the struct by name in an initializer. Before this, the initializer needed to contain just the values, for all fields, in order -- which still works, of course.
So for the following struct:
struct demo_s {
int first;
int second;
int third;
};
...you can use
struct demo_s demo = { 1, 2, 3 };
...or:
struct demo_s demo = { .first = 1, .second = 2, .third = 3 };
...or even:
struct demo_s demo = { .first = 1, .third = 3, .second = 2 };
...though the last two are for C99 only.
These are C99's designated initializers.
Its known as designated initialisation (see Designated Initializers). An "initializer-list", Each '.' is a
"designator" which in this case names a particular member of the
'fuse_oprations' struct to initialize for the object designated by
the 'hello_oper' identifier.
The whole syntax is known as designated initializer as already mentioned by COD3BOY and it is used in general when you need to initialize your structure at the time of declaration to some specific or default values.
Related
static struct fuse_oprations hello_oper = {
.getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
};
I don't understand this C syntax well. I can't even search because I don't know the syntax's name. What's that?
This is a C99 feature that allows you to set specific fields of the struct by name in an initializer. Before this, the initializer needed to contain just the values, for all fields, in order -- which still works, of course.
So for the following struct:
struct demo_s {
int first;
int second;
int third;
};
...you can use
struct demo_s demo = { 1, 2, 3 };
...or:
struct demo_s demo = { .first = 1, .second = 2, .third = 3 };
...or even:
struct demo_s demo = { .first = 1, .third = 3, .second = 2 };
...though the last two are for C99 only.
These are C99's designated initializers.
Its known as designated initialisation (see Designated Initializers). An "initializer-list", Each '.' is a
"designator" which in this case names a particular member of the
'fuse_oprations' struct to initialize for the object designated by
the 'hello_oper' identifier.
The whole syntax is known as designated initializer as already mentioned by COD3BOY and it is used in general when you need to initialize your structure at the time of declaration to some specific or default values.
I came across the following maze definition code:
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) {}
}
}
};
From the linked blog post I understand that they are trying to define the binary tree with the cheese in the diagram.
However I can't seem to make head or tail out of what the C code is supposed to do. It would be great if someone could explain it to me.
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).
This question already has answers here:
What does dot (.) mean in a struct initializer?
(4 answers)
Closed 9 years ago.
I wonder the meaning of attribute definitions with dot (.) for struct attributes in Redis source code :
struct config cfg = {
.tcp = {
.host = "127.0.0.1",
.port = 6379
},
.unix = {
.path = "/tmp/redis.sock"
}
};
Does it have a special meaning when you define an attribute with dot like .tcp = {...} ?
Thanks all.
It is a way to do named initialization of the struct members.
The default way to initialize a struct requires you to provide the arguments in the order the members were defined. This lets you you reorder that, and makes it more readable as well. This syntax also lets you initialize only a few members of the struct, esp. if they are not the first few. Take a look at this page.
... I wonder the meaning of attribute definitions with dot (.) for struct attributes ...
It allows for you to access a specific element of the structure using the initialization syntax { }. For example, consider this struct:
struct my_struct {
int field_1;
int field_2;
int field_3;
};
... it can be initialized as follows:
struct my_struct s1 = { 1, 2, 3 };
... or as follows:
struct my_struct s2 = { .field_1 = 1, .field_2 = 2, .field_3 = 3 };
... or if you do not know the order of the fields (or want to specify them in some order):
struct my_struct s3 = { .field_3 = 3, .field_1 = 1, .field_2 = 2 };
... remark that s1 is equivalent to s2 which is equivalent to s3. Moreover, if you do not specify a field in your initialization then it will be zero. From the C99 standard 6.7.8.21:
If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
... to illustrate this:
struct my_struct s4 = { .field_1 = 1 };
... that will zero-fill fields 2 and 3, hence s4.field_2 == 0 implies true.
looking at the linux kernel source, I found this:
static struct tty_operations serial_ops = {
.open = tiny_open,
.close = tiny_close,
.write = tiny_write,
.write_room = tiny_write_room,
.set_termios = tiny_set_termios,
};
I've never seen such a notation in C.
Why is there a dot before the variable name?
This is a Designated Initializer, which is syntax added for C99.
Relevant excerpt:
In a structure initializer, specify the name of a field to initialize
with ‘.fieldname =’ before the element value. For example, given the
following structure,
struct point { int x, y; };
the following initialization
struct point p = { .y = yvalue, .x = xvalue };
is equivalent to
struct point p = { xvalue, yvalue };
It's sometimes called "designated initialization". This is a C99 addition, though it's been a GNU extension for a while.
In the list, each . names a member of the struct to initialize, the so called designator.
I found some struct initialization code yesterday that threw me for a loop. Here's an example:
typedef struct { int first; int second; } TEST_STRUCT;
void testFunc() {
TEST_STRUCT test = {
second: 2,
first: 1
};
printf("test.first=%d test.second=%d\n", test.first, test.second);
}
Surprisingly (to me), here's the output:
-> testFunc
test.first=1 test.second=2
As you can see, the struct gets initialized properly. I wasn't aware labeled statements could be used like that. I've seen several other ways of doing struct initialization, but I didn't find any examples of this sort of struct initialization on any of the online C FAQs. Is anybody aware of how/why this works?
Here is the section of the gcc manual which explains the syntax of designated initializers for both structs and arrays:
In a structure initializer, specify the name of a field to initialize
with '.fieldname =' before the element value. For example, given the
following structure,
struct point { int x, y; };
the following initialization
struct point p = { .y = yvalue, .x = xvalue };
is equivalent to
struct point p = { xvalue, yvalue };
Another syntax which has the same meaning, obsolete since GCC 2.5, is 'fieldname:', as shown here:
struct point p = { y: yvalue, x: xvalue };
The relevant page can be found here.
Your compiler should have similar documentation.
These are neither labels nor bitfields.
This is a syntax to initialize struct members dating back to the days before C99. It is not standardized but available in e.g. gcc.
typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };
In C99, syntax for initializing specific struct members has been introduced for the first time in a standard, but it looks a little differently:
typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };
Yes, as pointed out above, these are designated initializers, which are standard C, though you should switch to using periods instead of colons. And as you note, most of the books out there are still stuck somewhere around 1984 in their syntax and fail to mention them. More fun facts:
--When using designated initializers, everything not specified is initialized at zero. This helps with exceptionally large structs, e.g.:
typedef struct {
double a, b, c, d, e;
char label[100];
} too_many_type;
too_many_type tm = {.a = 1, .e = 2, .b=1.5};
assert(tm.a + tm.b + tm.c + tm.d + tm.e == 4.5);
assert(!strlen(label));
--Also, you can use the compound literal form to use this form on a non-initialization line, e.g.:
too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};
These are really great features, and are supported by every C compiler that I can think of, being that it's the standard. It's a shame that they're not so well known.
It's not really "labeled statements", but a way to give initial values to the named fields in the struct.
Gcc gives a warning about "obsolete use of designated initializer with ':'", and in C99 you should instead write:
TEST_STRUCT test = {
.second = 2,
.first = 1
};
That syntax is not defined by the C Standard. Section 6.7.8 Initialization says
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
If your compiler accepts a designation with a colon without a diagnostic message it means your compiler is not (or is configured not to be) Standards compliant.