aleix's blog

Designated initializers

19 February 2007 10:02 am (c)

Last year, I discovered, thanks to the book "C, A Reference Manual", a great C99 feature: designated initializers. Designated initializers allow you to initialize components of an aggregate (structure, union or array) by specifying their names within an initializer list.

Arrays initialization

What most people normally use to initialize an array is the following idiom:

int v[4] = { 4, 2, 1, -5 };

in which you need to initialize each component of the array sequentially. Designated initializers allow you to specify which component of the array you want to initialize. Thus, we could write the line above as:

int v[4] = { [1] = 2, [2] = 1, [0] = 4, [3] = -5 };

Note that we have specified the component indexes which has allowed us to initialize the array with our desired order. If we do not initialize all the components, those not initialized will get 0 values. We can also mix both methods, so the line below would be also correct:

int v[4] = { [1] = 2, 1, [3] = -5 };

in which the component not referenced goes right after the named one.

A possible use of this kind of initializations would be a mapping between a list of identifiers and a list of strings.

// The public interface

typedef enum {
} id_t;

extern char const* string_by_id (id_t id);

// The private implementation

static char const* strings[] =
  [id_one] = "identifier one",
  [id_two] = "identifier two",
  [id_three] = "identifier three"

char const*
string_by_id (id_t id)
  return strings[id];

Structures and unions initialization

Designated initializers are also useful to initialize components of structures and unions by their name. In this case, the component to be initialized takes the form .c, where c is the name of the component. So, suppose we have the following structure:

struct point { float x; float y; float z; };

we could initialize each component of a struct point variable like this:

struct point my_point =
  .x = 0.34,
  .y = 0.98,
  .z = 1.56

With unions, we will use the same method, so having the following union:

union integer
  unsigned char int_8;
  unsigned short int int_16; 
  unsigned long int_32;

we can initialize it by any of its components:

union integer value = { .int_16 = 24000 };

Finally, we can merge both cases, so we can have arrays of structures or unions that can be initialized using designated initializers:

struct point pointvector[3] =
  [0].x = 0.34, [0].y = 1.78, [0].z = 3.18,
  [1] = { .x = 3.5, .y = 6.89 },
  [2] = { .y = 2.8, 1.23 }

14 responses

  1. David says:

    My favorite consequence of named initializers is this technique:

    struct a {
    int x;
    float y;
    char *z;

    void f1(struct a *);
    void f2()
    f1(&(struct a){.z="Hello", .y=.22, .x=10});

    Essentially you have a quick compact way of passing a struct into a function without needing a temporary variable. Obviously you can't do this if the function is going to hold on to the pointer or pass you something back in the structure (that you care about). But it comes in really handy.


  2. Nit Picker says:

    I agree about the usefulness of being be able to pass an 'immediate' struct as a parameter, but how is it a consequence of the named initializers feature ?

  3. dweej1 says:

    David - how is your example any different from the following?:
    f1(&(struct a){10, 22, "Hello"});

    If there is no difference, using named initializers doesn't provide anything special in your example.
    Also, in your example, would it be possible to assign a non-static to any of the struct members?:
    float foo = .1234;
    f1(&(struct a){.z=”Hello”, .y=foo, .x=10});

    If not, that further limits the usefulness of names initializers...

  4. aleix says:

    I think that the main reason for designated initializers is to help reading code. It doesn't provide any super extra cool feature, but it helps the reader to see the structure fields in an easy way (in the case of structures) or for example in the case of the string mapping I used in the post it also helps to read the code.

    In David's example it might help reading the code if the reader does not remember in which order the two integers go.

    And yes, this is possible:

    float foo = .1234;

    f1(&(struct a){.z=”Hello”, .y=foo, .x=10});

  5. laustan says:

    Arrays initialization is not a difficult task because if you know about how arrays are working then you also know about Arrays initialization. I prefer you to Arrays initialization in every array program.

  6. Programming Course Work says:

    Things are very open and intensely clear explanation of issues. was truly information. Your website is very beneficial.

  7. help with economics says:

    only professional writers can make this kind of material, cheers

  8. Kate says:

    I really like your blog post very much.

  9. bogdan22w3 says:

    How do you explain that?

  10. whatsapp plus says:

    Thanks a lot for sharing this useful information.

  11. freedom apk says:

    It is a nice post.

  12. creehack says:

    Really amazing article

  13. Stats Assignment Help Online says:

    Science Channel’s are giving a complete knowledge to its viewers about every thing students write done dissertation on this subjects and show its importance.

  14. Mary says:

    Thanks for the information your article brings.

Leave a Reply