48

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?

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Andrew Cottrell
  • 3,312
  • 3
  • 26
  • 41

5 Answers5

51

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.

Doodad
  • 1,518
  • 1
  • 15
  • 20
sigjuice
  • 28,661
  • 12
  • 68
  • 93
  • 3
    Excellent, that documentation clearly explains the syntax: Another syntax which has the same meaning, obsolete since GCC 2.5, is `fieldname:', as shown here: struct point p = { y: yvalue, x: xvalue }; – Andrew Cottrell Oct 21 '09 at 15:31
  • 1
    @AndrewCottrell, this "fieldname:" syntax looks so natural (and preferable) to me, any idea why it should be considered obsolete? – rick Jun 12 '17 at 04:25
  • 4
    @rick the "fieldname:" syntax is a gcc extension and has never been part of any ISO C standard. – sigjuice Jun 12 '17 at 05:51
34

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 };
ndim
  • 35,870
  • 12
  • 47
  • 57
  • 1
    Yep, I was aware of the designated initializer format. Unfortunately that format isn't compatible with C++! (Not in my testing anyway.) Thanks for the answer though. Good to know this is not standardized. – Andrew Cottrell Oct 21 '09 at 15:08
  • 9
    @Andrew you never said anything about C++ in your question – horseyguy Dec 17 '09 at 11:23
15

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.

bk.
  • 6,068
  • 2
  • 24
  • 28
  • 1
    The alternative syntax (using colons) looks so natural and preferable to me, could you clarify on why we should switch to using periods instead of colons? – rick Jun 12 '17 at 04:28
6

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
    };
Thomas Padron-McCarthy
  • 27,232
  • 8
  • 51
  • 75
3

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.

pmg
  • 106,608
  • 13
  • 126
  • 198