C struct initialization using labels. It works, but how?
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("tes开发者_JS百科t.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.
精彩评论