开发者

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 开发者_如何学Go= {1, 3, {4, 5, 6}};
}

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


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 );
}


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);


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.


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.


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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜