12

How can I initialize this nested struct in C?

typedef struct _s0 {
   int size;
   double * elems;
}StructInner ;

typedef struct _s1 {
   StructInner a, b, c, d, e;
   long f;
   char[16] s;
}StructOuter;  StructOuter myvar = {/* what ? */ };
Stick it to THE MAN
  • 5,621
  • 17
  • 77
  • 93

4 Answers4

20

To initialize everything to 0 (of the right kind)

StructOuter myvar = {0};

To initialize the members to a specific value

StructOuter myvar = {{0, NULL}, {0, NULL}, {0, NULL},
                     {0, NULL}, {0, NULL}, 42.0, "foo"};
/* that's {a, b, c, d, e, f, s} */
/* where each of a, b, c, d, e is {size, elems} */

Edit

If you have a C99 compiler, you can also use "designated initializers", as in:

StructOuter myvar = {.c = {1000, NULL}, .f = 42.0, .s = "foo"};
/* c, f, and s initialized to specific values */
/* a, b, d, and e will be initialized to 0 (of the right kind) */
pmg
  • 106,608
  • 13
  • 126
  • 198
  • Just to clarify, `StructOuter myvar = { 0 };` will do the same (0-initialization) for all inner structs, so we don't need to explicitly set those to `{0, NULL}`, right? – domsson Apr 28 '20 at 15:44
  • 1
    Yes @domsson, the `{ 0 }` initializer will 0-initialize everything, recursively when needed. – pmg Apr 28 '20 at 20:52
5

To highlight struct labels in particular:

StructInner a = {
    .size: 1,
    .elems: { 1.0, 2.0 }, /* optional comma */
};

StructOuter b = {
    .a = a, /* struct labels start with a dot */
    .b = a,
         a, /* they are optional and you can mix-and-match */
         a,
    .e = {  /* nested struct initialization */
        .size: 1,
        .elems: a.elems
    },
    .f = 1.0,
    .s = "Hello", /* optional comma */
};
Willem
  • 317
  • 2
  • 11
2
double a[] = { 1.0, 2.0 };
double b[] = { 1.0, 2.0, 3.0 };
StructOuter myvar = { { 2, a }, { 3, b }, { 2, a }, { 3, b }, { 2, a }, 1, "a" };

It seems a and b cannot be initialized in-place in plain C

Kcats
  • 884
  • 1
  • 15
  • 26
1

Following also works with GCC, C99. GCC doesnt complain about it. I am not sure if this is standard.

double arr[] = { 1.0, 2.0 };   // should be static or global
StructOuter myvar = 
{
    .f = 42,
    .s = "foo",
    .a.size = 2,
    .a.elems = &arr,
    .b.size = 0,  // you can explicitly show that it is zero
    // missing members will actually be initialized to zero
};
uffu
  • 43
  • 6