Pregunta C inicializar matriz dentro de la estructura


Quiero tener una matriz de longitud variable dentro de una estructura, pero tengo problemas para inicializarla correctamente.

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

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

Todo lo que intento me da un error 'error: inicialización no estática de un miembro de matriz flexible'.


22
2017-10-13 03:08


origen


Respuestas:


Puedes hacer que funcione en gcc haciendo que la estructura sea static o global, pero resulta que la inicialización de los miembros de la matriz flexible no es conforme y, por lo tanto, es probable que no funcione, excepto con gcc. Aquí hay una manera de hacerlo que solo usa características que cumplen con C99 ...

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

12
2017-10-13 03:12



Aquí está mi versión:

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

27
2017-10-13 04:18



no lo hagas tener una matriz de longitud variable (VLA) en su estructura. Lo que tienes en tu estructura se llama miembro de matriz flexible. El miembro de matriz flexible no tiene absolutamente nada que ver con VLA. Los miembros flexibles de la matriz en C existen para legalizar y soportar la vieja jerga de "struct hack", que se basa en la asignación dinámica de memoria para objetos struct con matrices finales de diferentes tamaños.

Los miembros de matriz flexibles no se pueden inicializar con inicializadores agregados, que es lo que parece intentar en su código. Lo que estás tratando de hacer aquí es simplemente imposible. No hay tal característica en C.

Mientras tanto, el texto del mensaje de error generado por el compilador parece sugerir que admite algo así como una extensión. Esto podría ser cierto, pero tenga en cuenta que esto no es de ninguna manera una característica estándar de C.


3
2017-10-13 03:41



No creo que esto sea posible o compatible. Como DigitalRoss señala, puede inicializar desde un literal en el caso de static matrices ... aunque todavía no estoy seguro de si esto está incluido en el estándar o simplemente una extensión común. Parece que no puedo encontrar una cláusula en el estándar que admita la inicialización literal de matrices flexibles, aunque puedo ver que gcc lo admite explícitamente.


1
2017-10-13 03:41



Una versión que usa 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
2017-10-13 03:37