user35288
user35288

Reputation:

C initialize array within structure

I want to have an variable-length array contained within a structure, but am having trouble initializing it correctly.

struct Grid {
  int rows;
  int cols;
  int grid[];
}

int main() {
  struct Grid testgrid = {1, 3, {4, 5, 6}};
}

Everything I try gives me an 'error: non-static initialization of a flexible array member' error.

Upvotes: 23

Views: 59295

Answers (5)

DigitalRoss
DigitalRoss

Reputation: 146231

You can make that work in gcc by making the struct either static or global, but it turns out that initializing flexible array members is non-conforming and so it is likely to not work except with gcc. Here is a way to do it that just uses C99-conforming features...

#include <stdlib.h>
#include <stdarg.h>

typedef struct Grid {
  int rows;
  int cols;
  int grid[];
} *Grid;

Grid newGrid(int, int, ...);

Grid newGrid(int rows, int cols, ...)
{
Grid g;
va_list ap;
int i, n = rows * cols;

  if((g = malloc(sizeof(struct Grid) + rows * cols * sizeof(int))) == NULL)
    return NULL;
  g->rows = rows;
  g->cols = cols;
  va_start(ap, cols);
  for(i = 0; i < n; ++i)
    g->grid[i] = va_arg(ap, int);
  va_end(ap);
  return g;
}
.
.
.
Grid g1, g2, g3;
g1 = newGrid(1, 1, 123);
g2 = newGrid(2, 3, 1, 1, 1,
                   2, 2, 2);
g3 = newGrid(4, 5, 1,  2,  3,  4,  5,
                   6,  7,  8,  9, 10,
                  11, 12, 13, 14, 15,
                  16, 17, 18, 19, 20);

Upvotes: 12

AnT stands with Russia
AnT stands with Russia

Reputation: 320739

You don't have a variable length array (VLA) in your structure. What you have in your structure is called a flexible array member. Flexible array member has absolutely nothing to do with VLA. Flexible array members in C exist to legalize and support the good-old "struct hack" idiom, which is based on dynamic allocation of memory for struct objects with trailing arrays of different size.

Flexible array members cannot be initialized with aggregate initializers, which is what you seem to attempt in your code. What you are trying to do here is simply impossible. There's no such feature in C.

Meanwhile, the text of the error message generated by your compiler seems to suggest that it supports something like this as an extension. This might be true, but keep in mind that this is in no way a standard C feature.

Upvotes: 4

sambowry
sambowry

Reputation: 2476

Here is my version:

#include <stdio.h> 

struct matrix {
  int rows;
  int cols;
  int **val;
} a = {        .rows=3,  .cols=1,
        .val = (int*[3]){ (int[1]){1},
                          (int[1]){2},
                          (int[1]){3} } },

  b = {        .rows=3,  .cols=4,
        .val = (int*[3]){ (int[4]){1, 2, 3, 4},
                          (int[4]){5, 6, 7, 8},
                          (int[4]){9,10,11,12} } };

void print_matrix( char *name, struct matrix *m ){
  for( int row=0;row<m->rows;row++ )
    for( int col=0;col<m->cols;col++ )
      printf( "%s[%i][%i]: %i\n", name, row, col, m->val[row][col] );
  puts("");
}

int main(){
  print_matrix( "a", &a );
  print_matrix( "b", &b );
}

Upvotes: 29

D.Shawley
D.Shawley

Reputation: 59623

I do not believe that this is possible or supported. As DigitalRoss points out, you can initialize from a literal in the case of static arrays... though I'm still not sure if this is included in the Standard or just a common extension. I can't seem to find a clause in the Standard that supports literal initialization of flexible arrays though I can see that gcc explicitly supports it.

Upvotes: 1

Macarse
Macarse

Reputation: 93173

A version using malloc:

#include <stdio.h>
#include <stdlib.h>

typedef struct Grid {
  int rows;
  int cols;
  int *grid;
} Grid;

/* Should validate params */
Grid
buildGrid(int rows, int cols, int vec[]) {

    Grid grid;
    grid.rows = rows;
    grid.cols = cols;
    int i;

    if ( (grid.grid = malloc(sizeof(vec))) == NULL ) {
        /* do something.*/
    }

    for(i = 0; i < sizeof(vec) ; i++ ) {
        grid.grid[i] = vec[i];
    }

    return grid;
}

Upvotes: -1

Related Questions