comment utiliser un tableau flexible en C pour conserver plusieurs valeurs?

J’ai le code suivant:

typedef struct { int name; int info[1]; } Data; 

alors j’ai cinq variables:

 int a, b, c, d, e; 

comment puis-je l’utiliser comme un tableau flexible pour conserver toutes les valeurs des cinq variables?

Pour le faire correctement, vous devez déclarer le membre du tableau flexible comme un type incomplet:

 typedef struct { int name; int info[]; } Data; 

Allouez ensuite la mémoire de manière dynamic avec

 Data* data = malloc(sizeof(Data) + sizeof(int[N])); for(int i=0; iinfo[i] = something; // now use it just as any other array } 

MODIFIER

Assurez-vous que vous utilisez un compilateur C99 pour que cela fonctionne, sinon vous rencontrerez divers problèmes:

Si vous allouez un tableau de longueur 1, vous devrez alors malloc 1 pour le premier élément du tableau avec la structure, puis vous appendez N octets par la suite. Ce qui signifie que vous allouez actuellement N+1 octets. Ce n’est peut-être pas ce que l’on avait l’intention de faire et cela complique inutilement les choses.

(Pour résoudre le problème ci-dessus, GCC disposait d’une extension antérieure à C99 qui autorisait les tableaux de longueur nulle, ce qui n’est pas autorisé dans le standard C.)

Avant C99, ou dans tout autre contexte que celui d’un membre de tableau flexible, C n’autorise pas les types de tableaux incomplets tels que ceux indiqués dans mon code.

C99 garantit que votre programme est bien défini lorsque vous utilisez un membre de groupe flexible. Si vous n’utilisez pas C99, le compilateur peut alors append des octets “struct padding” entre les autres membres de la structure et le tableau à la fin. Ce qui signifie que data->info[0] pourrait pointer sur un octet de remplissage et non sur le premier élément de votre tableau alloué. Cela peut entraîner toutes sortes de comportements étranges et inattendus.

C’est pourquoi les membres du groupe flexible ont été appelés “struct hack” avant C99. Ils n’étaient pas fiables, juste un bidouillage sale qui peut ou peut ne pas fonctionner.

Ce type de structure est un langage assez courant en C; L’idée est que vous allouez un espace supplémentaire à la fin de la struct , où les éléments d’ info après le premier sont réellement stockés. Le membre de tableau de taille 1 à la fin de la struct vous permet ensuite d’utiliser la syntaxe de tableau pour accéder à ces données.

Si vous voulez stocker 5 éléments, vous devrez faire:

 Data * data=malloc(sizeof(Data)+sizeof(int)*4); /* 4 because the first element is already included in the size of the struct */ /* error checking omitted ... */ data->info[0]=a; data->info[1]=b; data->info[2]=c; data->info[3]=d; data->info[4]=e; /* ... */ /* when you don't need d anymore remember to deallocate */ free(data); 

Vous pouvez également écrire une fonction d’assistance pour faciliter l’allocation:

 Data * AllocateData(size_t elements) { if(elements==0) return NULL; return malloc(sizeof(Data)+sizeof(int)*(elements-1)); } 

et l’exemple ci-dessus serait

 Data * data=AllocateData(5); /* then as above */ 

Ceci s’appelle des tableaux flexibles et a été introduit dans C99. Souvent appelé un bidouillage struct aussi. En C99, le membre de groupe flexible doit être déclaré sans taille.

Vous devez allouer dynamicment de la mémoire pouvant contenir plus de mémoire que la taille de la structure. Comme le tableau est le dernier membre de la structure, vous pouvez l’indexer au-delà de sa taille, à condition de lui allouer suffisamment de mémoire.

  typedef struct { int name; int info[1]; } Data; Data *d = malloc(sizeof(*d) + (5 * sizeof(int)); //enough for the struct and 5 more ints. //we have enough room for 6 elements in the info array now //since the struct has room for 1 element, and we allocated room for another 5 ints d->info[0] = 1; d->info[1] = 2; d->info[2] = 3; d->info[3] = 4; d->info[4] = 5; d->info[5] = 6; 

Utilisation d’un membre du tableau avec 1 taille int info[1]; de cette manière est un comportement techniquement indéfini – mais fonctionnera bien sur de nombreux compilateurs populaires. Avec un compilateur C99, cela est pris en charge par un membre de groupe flexible déclaré comme int info[]; . Lire la suite ici