Nulik Nulik - 2 months ago 14
C Question

initializing array of pointers to structs

How do I initialize an array of structs without creating intermediate array of list of pointers to these structs? Consider the following example code:

snippets $ cat a2p.c
struct shape {
int angles;
char shape_name[16];
};
typedef struct shape shape_t;
struct container {
char name[32];
shape_t **elements;
int num_elts;
};
typedef struct container container_t;

shape_t triangle = {
.angles = 3,
.shape_name = {"Triangle"}
};
shape_t rectangle = {
.angles = 4,
.shape_name = {"Rectangle"}
};

container_t c = {
.name = {"Case"},
.elements = {
&triangle,
&rectangle
},
.num_elts =2
};


int main(void) {

return 0;

}


I need the .elements member to point to an array of pointers to shape_t sturcts, but this code does not compile:

snippets $ gcc -c a2p.c
a2p.c:24:2: warning: braces around scalar initializer
.elements = {
^
a2p.c:24:2: note: (near initialization for ‘c.elements’)
a2p.c:25:3: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
&triangle,
^
a2p.c:25:3: note: (near initialization for ‘c.elements’)
a2p.c:26:3: warning: excess elements in scalar initializer
&rectangle
^
a2p.c:26:3: note: (near initialization for ‘c.elements’)
snippets $


However , if I add an intermediate array , like this:

shape_t *shapes[] = {
&triangle,
&rectangle
};
container_t c = {
.name = {"Case"},
.elements = shapes,
.num_elts =2
};


The code compiles ok. Can I avoid creating the shapes[] array as an intermediate step and directly initialize container_t with all data like on the first code snippet? What would be the correct initialization syntax then?

Answer

You are almost there; you just need to ensure that the elements initializer is a suitable pointer, like this:

struct shape {
    int     angles;
    char    shape_name[16];
};
typedef struct shape shape_t;
struct container {
    char            name[32];
    shape_t         **elements;
    int             num_elts;
};
typedef struct container container_t;

shape_t triangle = {
    .angles     = 3,
    .shape_name = { "Triangle" }
};
shape_t rectangle = {
    .angles     = 4,
    .shape_name = { "Rectangle" }
};

container_t c = {
    .name       = { "Case" },
    .elements   =  (shape_t *[]) {
        &triangle,
        &rectangle,
    },
    .num_elts   = 2,
};

int main(void) {
    return 0;
}

Note the use of a compound literal for the array of pointers to shape_t elements.

Comments