Well here is a question for you all.
Whenever I look at any source file of linux-kernel, I usually find some code similar to the one shown below.
What is going on here in this piece of code?
These are called designated initializer for structs.
Using C89-style initialization, the following example shows how you would initialize the first union member birthday of the union variable people:
C only
Whenever I look at any source file of linux-kernel, I usually find some code similar to the one shown below.
What is going on here in this piece of code?
1 | static struct scsi_host_template qla4xxx_driver_template = { |
These are called designated initializer for structs.
An initializer for a structure is a brace-enclosed comma-separated list of values, and for a union, a brace-enclosed single value. The initializer is preceded by an equal sign (=).
C99 and C++ allow the initializer for an automatic member variable of a union or structure type to be a constant or non-constant expression.
There are two ways to specify initializers for structures and unions:
- With C89-style initializers, structure members must be initialized in the order declared, and only the first member of a union can be initialized.
Using C89-style initialization, the following example shows how you would initialize the first union member birthday of the union variable people:
union {
char birthday[9];
int age;
float weight;
} people = {"23/07/57"};
- Using designated initializers, a C99 feature which allows you to name members to be initialized, structure members can be initialized in any order, and any (single) member of a union can be initialized.
C only
Using a designated initializer in the same example, the following initializes the second union member age :
union {
char birthday[9];
int age;
float weight;
} people = { .age = 14 };
End of C only
Designated initializers, a C99 feature, are supported for aggregate types, including arrays, structures, and unions. A designated initializer, or designator, points out a particular element to be initialized. A designator list is a comma-separated list of one or more designators. A designator list followed by an equal sign constitutes a designation.
Designated initializers allow for the following flexibility:
- Elements within an aggregate can be initialized in any order.
- The initializer list can omit elements that are declared anywhere in the aggregate, rather than only at the end. Elements that are omitted are initialized as if they are static objects: arithmetic types are initialized to 0; pointers are initialized to NULL.
- Where inconsistent or incomplete bracketing of initializers for multi-dimensional arrays or nested aggregates may be difficult to understand, designators can more clearly identify the element or member to be initialized.
Designator list syntax for structures and unions
.-,------------------------.
V |
>>-{----.--member--=--expression-+--}--------------------------><
Designator list syntax for arrays
.-,----------------------------------------.
| .-----------------------. |
V V | |
>>-{------[--array subscript--]-+--=--expression-+--}----------><
In the following example, the designator is .any_member and the designated initializer is .any_member = 13:
union { /* ... */ } caw = { .any_member = 13 };
The following example shows how the second and third members b and c of structure variable klm are initialized with designated initializers:
struct xyz {
int a;
int b;
int c;
} klm = { .a = 99, .c = 100 };
In the following example, the third and second elements of the one-dimensional array aa are initialized to 3 and 6, respectively:
int aa[4] = { [2] = 3, [1] = 6 };
The following example initializes the first four and last four elements, while omitting the middle four:
static short grid[3] [4] = { [0][0]=8, [0][1]=6,
[0][2]=4, [0][3]=1,
[2][0]=9, [2][1]=3,
[2][2]=1, [2][3]=1 };
The omitted four elements of grid are initialized to zero:
Element | Value | Element | Value |
---|---|---|---|
grid[0] [0] | 8 | grid[1] [2] | 0 |
grid[0] [1] | 6 | grid[1] [3] | 0 |
grid[0] [2] | 4 | grid[2] [0] | 9 |
grid[0] [3] | 1 | grid[2] [1] | 3 |
grid[1] [0] | 0 | grid[2] [2] | 1 |
grid[1] [1] | 0 | grid[2] [3] | 1 |
Designated initializers can be combined with regular initializers, as in the following example:
int a[10] = {2, 4, [8]=9, 10}
In this example, a[0] is initialized to 2, a[1] is initialized to 4, a[2] to a[7] are initialized to 0, and a[9] is initialized to 10.
In the following example, a single designator is used to "allocate" space from both ends of an array:
int a[MAX] = {
1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
};
The designated initializer, [MAX-5] = 8, means that the array element at subscript MAX-5 should be initialized to the value 8. If MAX is 15, a[5] througha[9] will be initialized to zero. If MAX is 7, a[2] through a[4] will first have the values 5, 7, and 9, respectively, which are overridden by the values 8, 6, and4. In other words, if MAX is 7, the initialization would be the same as if the declaration had been written:
int a[MAX] = {
1, 3, 8, 6, 4, 2, 0
};
You can also use designators to represent members of nested structures. For example:
struct a {
struct b {
int c;
int d;
} e;
float f;
} g = {.e.c = 3 };
initializes member c of structure variable e, which is a member of structure variable g, to the value of 3.
Unnamed structure or union members do not participate in initialization and have indeterminate value after initialization. Therefore, in the following example, the bit field is not initialized, and the initializer 3 is applied to member b:
struct {
int a;
int :10;
int b;
} w = { 2, 3 };
The default initializer for a union with static storage is the default for the first component; a union with automatic storage has no default initialization.
The following definition shows a partially initialized structure:
struct address {
int street_no;
char *street_name;
char *city;
char *prov;
char *postal_code;
};
struct address temp_address =
{ 44, "Knyvet Ave.", "Hamilton", "Ontario" };
The values of temp_address are:
Member | Value |
---|---|
temp_address.street_no | 44 |
temp_address.street_name | address of string "Knyvet Ave." |
temp_address.city | address of string "Hamilton" |
temp_address.prov | address of string "Ontario" |
temp_address.postal_code | Depends on the storage class of the temp_address variable; if it is static, the value would be NULL. |
C only
To initialize only the third and fourth members of the temp_address variable, you could use a designated initializer list, as follows:
struct address {
int street_no;
char *street_name;
char *city;
char *prov;
char *postal_code;
};
struct address temp_address =
{ .city = "Hamilton", .prov = "Ontario" };
End of C only