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.
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).
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.
While reading a code I came across, the following definition and initialization of a struct:
// header file
struct foo{
char* name;
int value;
};
//Implementation file
struct foo fooElmnt __foo;
// some code using fooElmnt
struct foo fooElmnt __foo = {
.name = "NAME";
.value = some_value;
}
What does this mean in C and how is it different from usual declarations?
It's called designated initialization,
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 };
If you read on, it explains that .fieldname is called a designator.
UPDATE: I'm no C99 expert, but I couldn't compile the code. Here's the changes I had to make:
// header file
struct foo{
char* name;
int value;
};
//Implementation file
//struct foo fooElmnt __foo;
// some code using fooElmnt
struct foo fooElmnt = {
.name = "NAME",
.value = 123
};
Were you able to compile it? I used TCC.
Those are designated initializers, introduced in c99. You can read more here
Without them, you'd use
struct foo fooElmnt __foo = {
"NAME",
some_value
};
While in this case it doesn't matter much - other than the c99 way is more verbose, and its easier to read which element is initialized to what.
It does help if your struct has a lot of members and you only need to initialize a few of them to something other than zero.
This is a designated initialization. This also initializing the fields by their name, which is more readable than anomynous initialization when the structures are getting large. This has been introduced by the C99 standard.
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.