Search code examples
arrayscinitializationstructure

Compact way to initialize an array of structures in C?


I've got a rather messy way to initialize an array of structures, and I'm hoping someone can help me find a more compact method. My structure is:

struct Vertex_t {
  int i; /* Label */
  int n; /* Order (number of 2D simplicies it is contained within) */
  int r[3]; /* Position of vertex, for plotting */
}; 

And I need a bunch of these, so I'm preparing an array of them:

struct Vertex_t v_list[VERT_MAX]

So now I need to set the ones I'm initially using (4 here, but in principle, it will be more):

int N_t=4;
for (i=0;i<N_v;i++){
    v_list[i].i=i;
    v_list[i].n=1;
}
v_list[0].r[0]=0;
v_list[0].r[1]=1;
v_list[0].r[2]=0;
.../* for each i*/

So I can loop through to set the initial numbers, but for the array r (playing the role of a 3D vector here), I have to set each one individually (each value of r[] must be set by hand....I think). The above works, but I'd much rather use something like

v_list[0].r[]={0,1,0};

or even

v_list[i]={.i=i,.n=1, .r={0,1,0}};

But I know neither of them works because I've already got the memory for v_list[i] reserved.

Does anyone have a way to get what I'm going for? I need a large number of structures in an array, and I'd like to set them as if I was initializing them.


Solution

  • for the array r (playing the role of a 3D vector here), I have to set each one individually (each value of r[] must be set by hand....I think). The above works, but I'd much rather something like

    v_list[0].r[]={0,1,0};
    

    or even

    v_list[i]={.i=i,.n=1, .r={0,1,0}};
    

    C has array initialization but not (whole-)array assignment. If you want to avoid individual element assignments then these are some of your better options:

    1. Use a bona fide initializer in the declaration instead of initialization code:
      struct Vertex_t v_list[VERT_MAX] = {
          { .i = 0, .n = 1, .r = {0, 0, 0} },
          { .i = 1, .n = 1, .r = {1, 1, 0} },
          { .i = 2, .n = 1, .r = {0, 1, 1} },
          { .i = 3, .n = 1, .r = {1, 0, 1} }
          // other elements will be default-initialized
      };
      
    2. Assign from compound literal structures (the array inside does not prevent this):
      struct Vertex_t v_list[VERT_MAX];
      
      // Possibly this can be looped:
      v_list[0] = (struct Vertex_t) { .i = 0, .n = 1, .r = {0, 0, 0} };
      v_list[1] = (struct Vertex_t) { .i = 1, .n = 1, .r = {1, 1, 0} };
      v_list[2] = (struct Vertex_t) { .i = 2, .n = 1, .r = {0, 1, 1} };
      v_list[3] = (struct Vertex_t) { .i = 3, .n = 1, .r = {1, 0, 1} };
      // other elements of `v_list` are not initialized
      
    3. memcpy() the array members from compound literals:
      for (i = 0; i < 4; i++) {
          v_list[i].i=i;
          v_list[i].n=1;
      }
      memcpy(v_list[0].r, (int[]) {0, 0, 0}, sizeof(v_list[0].r));
      memcpy(v_list[1].r, (int[]) {1, 1, 0}, sizeof(v_list[1].r));
      memcpy(v_list[2].r, (int[]) {0, 1, 1}, sizeof(v_list[2].r));
      memcpy(v_list[3].r, (int[]) {1, 0, 1}, sizeof(v_list[3].r));
      
    4. Like (3), but copy from local static arrays of const int instead of from compound literals.