web-dev-qa-db-fra.com

C initialiser le tableau dans la structure

Je veux avoir un tableau de longueur variable contenu dans une structure, mais j'ai du mal à l'initialiser correctement.

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

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

Tout ce que j'essaye me donne une erreur "erreur: initialisation non statique d'un membre de tableau flexible".

22
user35288

Vous pouvez faire en sorte que cela fonctionne dans gcc en rendant la structure static ou globale, mais il s'avère que l'initialisation des membres du tableau flexible n'est pas conforme et il est donc probable qu'elle ne fonctionne que avec gcc. Voici une façon de le faire qui utilise simplement des fonctionnalités conformes à 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
DigitalRoss

Voici ma 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 );
}
27
sambowry

Vous ne pas avez un tableau de longueur variable (VLA) dans votre structure. Ce que vous avez dans votre structure est appelé membre du tableau flexible. Un membre de baie flexible n'a absolument rien à voir avec VLA. Les membres de tableau flexibles en C existent pour légaliser et prendre en charge le bon vieux idiome "struct hack", qui est basé sur l'allocation dynamique de mémoire pour les objets struct avec des tableaux de fin de taille différente.

Les membres de tableau flexibles ne peuvent pas être initialisés avec des initialiseurs agrégés, ce que vous semblez tenter dans votre code. Ce que vous essayez de faire ici est tout simplement impossible. Il n'y a pas une telle fonctionnalité en C.

Pendant ce temps, le texte du message d'erreur généré par votre compilateur semble suggérer qu'il prend en charge quelque chose comme ça en tant qu'extension. Cela peut être vrai, mais gardez à l'esprit qu'il ne s'agit en aucun cas d'une fonctionnalité C standard.

4
AnT

Je ne pense pas que cela soit possible ou soutenu. Comme DigitalRoss le fait remarquer, vous pouvez initialiser à partir d'un littéral dans le cas des tableaux static ... bien que je ne sois toujours pas sûr si cela est inclus dans la norme ou juste un commun extension. Je n'arrive pas à trouver une clause dans la norme qui prend en charge l'initialisation littérale des tableaux flexibles bien que je puisse voir que gcc le prend explicitement en charge .

1
D.Shawley