What is tagged structure initialization syntax?

struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};

This declaration uses the standard C tagged structure initialization syntax.

Can someone elaborate?


Solution 1:

When you use aggregate initializers (initializers in {}) in the "traditional" ANSI C language (C89/90), you have to supply an individual initializer for each structure member in order, beginning with the first. For example

struct S { int a, b, c, d; };

struct S s = { 1, 2, 3, 4 };
/* 1 for `s.a`, 2 for `s.b` and so on... */

You are not required to specify initializers for all members, i.e. you can stop at any time (remaining members will be zero-initialized).

If for some reason you only cared to explicitly initialize the third member of the structure, you had to supply "dummy" explicit initializers for the first and the second members (just to get to the desired third)

/* We only care to explicitly initialize `s.c` */
struct S s = { 0, 0, 3 };
/* but we have to explicitly initialize `s.a` and `s.b` as well */

or abandon specific initialization entirely (likely replacing it with generic = { 0 }) and use a subsequent assignment to specific members

struct S s = { 0 };
s.c = 3;

One notable benefit of this assignment-based approach is that it is independent from the position of member c in the declaration of struct S.

The new specification of C language (C99) allows you to use "tagged" initializers by supplying the desired member name within the {}

struct S s = { .c = 3 };

That way you only explicitly initialize the desired member(s) (and have the compiler to zero-initialize the rest). This not only saves you some typing but also makes the aggregate initializers independent from the order in which the members are specified in the struct type declaration.

Aggregate initializers, as you probably know, can be used with arrays, too. And C99 supports "tagged" initialization with arrays as well. How the "tags" look in case of an array is illustrated by the following example

int a[10] = { [5] = 3 };
/* `a[5]` is initialized with 3, the rest of `a` is zero-initialized */

It is worth noting one more time that C language continues to stick to the "all or nothing" approach to aggregate initialization: if you specify an explicit initializer for just one (or some) members of a struct or an array, the whole aggregate gets initialized, and the members without explicit initializers get zero-initialized.

Solution 2:

You're using the names of the members of the structure to initialise the structure. i.e. each member initialisation is "tagged" with that member's name.

Solution 3:

Another benefit worth mention regarding this type of initialization is that it allows the reordering of structure members, which in some cases, can make performance improvements by, for instance ,placing pointers to frequently accessed members in the same hardware cache line.