Est-ce que cette utilisation d’un tableau Undefined Behavior?

Dans une solution que j’ai postée, j’ai reçu des commentaires indiquant que la solution contenait un comportement non défini. Cependant, je ne vois pas comment. La base de la solution affichée est:

typedef struct { int n; int a[1]; } t_x; void example(void) { int i; t_x *t= malloc (sizeof(t_x) + 99*sizeof(int)); t->n= 100; for (i=0; i n; i++) t->a[i]= i; free(t); } 

Le commentaire de UB centré sur si le tableau a maintenant 1 élément (tel que déclaré) ou a 100 éléments (tel qu’alloué).

Les parties de la norme citées étaient 6.5.6 (addition de pointeur / int) et 6.5.2.1 (indice en tableau)

  • “6.5.6 définit ce qui se passe lorsque vous ajoutez un pointeur et un entier. Le pointeur résultant pointe sur un élément correspondant du tableau, si un tel élément existe , ou sur un élément situé au-delà de la fin. Sinon, le résultat n’est pas défini.”

  • “6.5.2.1 définit ce a[n] signifie en termes de a+n . Il s’ensuit que vous ne pouvez pas dire a[n] si a n’a pas au moins n+1 éléments.”

Avec les deux citations, le commentateur semble impliquer que l’élément a[99] n’existerait pas. Cependant, en regardant la disposition de la mémoire, il existe clairement:

entrez la description de l'image ici

S’il vous plaît, aidez-moi à comprendre si / pourquoi c’est UB et quels types d’UB je peux m’attendre.

C’est un truc assez populaire dans le code pré-C99. Cela fonctionne dans de nombreuses implémentations, mais n’est pas à proprement parler légal (donc non portable). La norme ne dit pas comment la structure de t_x s’aligne en mémoire. Voir C FAQ pour plus de détails.

C99 a introduit un tableau de longueur flexible, ce qui est préférable pour ce type de problème.

Ok, le problème est que vous voulez allouer de la mémoire pour une table, que vous avez définie dans le code. Comme vous avez écrit cette table sera toujours de la taille un, vous pourrez donc y stocker un object de type int.

Si vous souhaitez allouer de la mémoire de manière dynamic pour a, vous devez alors:

 typedef struct { int n; int* a; } t_x; 

et alors

 t_x someStruct; someStruct.a=(int*)malloc(numberOfElements*sizeof(int));