In code example of Intel DPDK i have found this strange syntactical construction. Can anybody explain me what does it mean?
static const struct rte_eth_conf port_conf = {
.rxmode = {
.split_hdr_size = 0,
.header_split = 0,
.hw_ip_checksum = 0,
.hw_vlan_filter = 0,
.jumbo_frame = 0,
.hw_strip_crc = 0,
},
.txmode = {
}
};
It's a C99 syntax known as a designated initializer.
In earlier C standards, the elements of a struct initializer had to appear in the same order as in the struct definition. With designated initializers, that restriction is lifted. Naturally the struct members have to be named to indicate which member is being initialized.
Designated initializers can also be used with arrays and allow you to initialize specific elements of an array. For example:
int a[6] = { [4] = 29, [2] = 15 };
If you have
struct X
{
type_a var_a;
type_b var_b;
type_c var_c;
type_d var_d;
};
you can initialize an object like this:
struct X x = {value_a, value_b, value_c, value_d};
But this means you need to know the order of variables in X as well as having an initial value for all of it. Alternatively, you can initialize like this:
struct X x = {
.var_a = value_a,
.var_b = value_b,
.var_c = value_c,
.var_d = value_d
};
This way, you can initialize member variables in any order, or even skip some.
This is specially useful in a library where you have some variables needed to be initialized by the user, while other variables are more internal and could even be changed with different versions of your library. Using this kind of initialization, the user doesn't need to know about those extra variables.
This is C99 feature called designated initializers. It lets you specify the names of the fields to which you set values, rather than specifying the values in the order the corresponding fields appear in the declaration. Additionally, this syntax lets you initialize members of unions other than the first one - something that was impossible before C99.
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.
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.
I have the following question: How are anonymous structures (or unions) properly initialized according to the current C1X draft? Is this legal:
struct foo {
int a;
struct {
int i;
int j;
};
int b;
};
struct foo f = { 1, 2, 3, 4 };
struct foo g = { 1, { 2 }, 3 };
In GCC, g.j == 0 and g.b == 3, while in tcc g.j == 3 and g.b == 0. The current draft says:
"[...] unnamed members of objects of structure and union type do not participate in initialization. Unnamed members of structure objects have indeterminate value even after initialization.".
Can this be really true? Isn't
struct foo h = { 0 };
supposed to set all members to 0?
Thanks very much!
UPDATE:
Since anonymous members seem to be only useful when mixing structs/unions, how to initialize this correctly:
struct bar {
int tag;
union {
double d;
int i;
};
};
? This gives errors in gcc < 4.6 and icc 11, but works in gcc 4.6, icc 12, clang and tcc:
struct bar a = { .tag = 1, .i = 42 };
This gives errors in clang and tcc, but works in gcc and icc:
struct bar b = { .tag = 1, { .i = 42 } };
Is the second one a violation of the standard?
f and h should correctly initialize all members, as i and j are to be treated like members of struct foo (C1x 6.7.2.1 §13):
The members of an anonymous structure
or union are considered to be members
of the containing structure or union.
I don't think that gcc's initialization of g is correct, considering C1x 6.7.9 §9:
Except where explicitly stated
otherwise, for the purposes of this
subclause unnamed members of objects
of structure and union type do not
participate in initialization.
§20 - which deals with sub-aggregates - contains no explicit statement relevant to the issue, so my best guess would be that §9 applies (but only to the aggregate itself, not to its members!).
The bottom line is that anonymous sub-aggregates don't exist as separate objects, ie tcc's behaviour should be correct...
Example code for my take on the issue:
struct foo
{
struct bar { int i; }; // (1) unnamed, but tagged, ie *not* anonymous
struct { int j; }; // (2) unnamed, but anonymous
struct { int k; } baz; // (3) named, but not tagged
};
(1) takes no part in initialization, (2) initializes as though struct foo had an additional member named j, (3) initializes as a regular sub-aggregate.
If my interpretation is correct, anonymous structures only make sense if contained within a union: an anonymous structure within a structure is indistinguishable from a flat structure containing additional members.
All members that have names in your structure can be initialized. You just can't initialize the intermediate structures as such. But
struct foo f = { .a = 1, .i = 2, .j = 3, .b = 4 };
should do it.
I haven't read the draft, I'm pretty sure unnamed and anonymous members are different. Unnamed would be something like
struct foo {
int bar:1; /* named */
int :31; /* unnamed */
};
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.
Why can't we initialize members inside a structure ?
example:
struct s {
int i = 10;
};
If you want to initialize non-static members in struct declaration:
In C++ (not C), structs are almost synonymous to classes and can have members initialized in the constructor.
struct s {
int i;
s(): i(10)
{
}
};
If you want to initialize an instance:
In C or C++:
struct s {
int i;
};
...
struct s s_instance = { 10 };
C99 also has a feature called designated initializers:
struct s {
int i;
};
...
struct s s_instance = {
.i = 10,
};
There is also a GNU C extension which is very similar to C99 designated initializers, but it's better to use something more portable:
struct s s_instance = {
i: 10,
};
The direct answer is because the structure definition declares a type and not a variable that can be initialized. Your example is:
struct s { int i=10; };
This does not declare any variable - it defines a type. To declare a variable, you would add a name between the } and the ;, and then you would initialize it afterwards:
struct s { int i; } t = { 10 };
As Checkers noted, in C99, you can also use designated initializers (which is a wonderful improvement -- one day, C will catch up with the other features that Fortran 66 had for data initialization, primarily repeating initializers a specifiable number of times). With this simple structure, there is no benefit. If you have a structure with, say, 20 members and only needed to initialize one of them (say because you have a flag that indicates that the rest of the structure is, or is not, initialized), it is more useful:
struct s { int i; } t = { .i = 10 };
This notation can also be used to initialize unions, to choose which element of the union is initialized.
Note that in C++ 11, the following declaration is now allowed:
struct s {
int i = 10;
};
This is an old question, but it ranks high in Google and might as well be clarified.
Edit2: This answer was written in 2008 and relates to C++98. The rules for member initialization have changed in subsequent versions of the language.
Edit: The question was originally tagged c++ but the poster said it's regarding c so I re-tagged the question, I'm leaving the answer though...
In C++ a struct is just a class which defaults for public rather than private for members and inheritance.
C++ only allows static const integral members to be initialized inline, other members must be initialized in the constructor, or if the struct is a POD in an initialization list (when declaring the variable).
struct bad {
static int answer = 42; // Error! not const
const char* question = "what is life?"; // Error! not const or integral
};
struct good {
static const int answer = 42; // OK
const char* question;
good()
: question("what is life?") // initialization list
{ }
};
struct pod { // plain old data
int answer;
const char* question;
};
pod p = { 42, "what is life?" };
We can't initialize because when we declared any structure than actually what we do, just inform compiler about their presence i.e no memory allocated for that and if we initialize member with no memory for that. Normally what happens when we initialize any variable that depends on the place where we declared variable compiler allocate memory for that variable.
int a = 10;
if it's auto than in stack memory going to allocate
if it's global than in data sections memory going to allocate
So what memory is required to hold that data but in case of structure no memory is there so not possible to initialize it.
As you said it's just a member not a variable. When you declare a variable the compiler will also provide memory space for those variables where you can put values. In the case a of a struct member the compiler is not giving memory space for it, so you cannot assign values to struct members unless you create a variable of that struct type.