Les flexible array members du C99

L’une des nouveautés du C99 a été l’utilisation des flexible array members dans les structures. Cette fonctionnalité est décrite dans la partie 6.7.2.1, point 16, de la norme. Un flexible array member est un tableau de type incomplet, c’est-à-dire dont la taille n’est pas spécifiée. Seul le dernier élément d’une structure peut être un tableau flexible. Voici la déclaration d’une telle structure :

typedef struct
{
    unsigned int longueur;
    float tableauFlexible[];
} flexibilite

La taille du tableau flexible sera définie lors de la création de chaque nouvel objet de type flexibilite. Toute la question est de savoir comment définir la taille et surtout comment remplir ce tableau. Une méthode naïve et mauvaise serait de faire :

#include
#include

typedef struct
{
    unsigned int longueur;
    float tableauFlexible[];
} flexibilite;

int main(void)
{
    unsigned int i;
    flexibilite s;

    s.longueur = 5;

    for (i = 0; i < s.longueur; i++)
        s.tableauFlexible[i] = i;

    puts("Il faut etre flexible !");
    return 666;
}

En effet, la déclaration d’une structure flexibilite ne réserve aucun espace mémoire pour le tableau flexible et la boucle for a toutes ses chances de générer une erreur de segmentation. C’est le cas quand je teste ce code sous Windows XP avec CodeBlocks. Pour vérifier que la déclaration d’une telle structure ne réserve pas d’espace pour le tableau flexible, vous pouvez consulter la page sizeof de Wikipedia anglais (plus particulièrement tester le second code fourni dans cette section).

Quand on travaille avec une structure contenant un flexible array member, il est obligatoire de passer par un pointeur sur structure (1) et non par une structure directement. On pourra alors allouer la mémoire nécessaire pour stocker la structure et le tableau flexible. Voici un exemple de code valide :

#include
#include

typedef struct
{
    unsigned int longueur;
    float tableauFlexible[];
} flexibilite;

int main(void)
{
    unsigned int i;
    unsigned int longueur = 5;
    flexibilite *pt_s;

    pt_s = malloc( sizeof(flexibilite) + sizeof(float[longueur]) );

    pt_s->longueur = longueur;

    for (i = 0; i < pt_s->longueur; i++)
        pt_s->tableauFlexible[i] = i;

    puts("Il faut etre flexible !");
    return 666;
}

Pour plus de bonnes pratiques quant à l’utilisation des structures avec un flexible array member, je vous renvoie à l’excellent article MEMxx-C. Understand how flexible array members are to be used de la section Secure Coding du site Software Engineering Institute.

(1) Si vous travaillez avec gcc, il est possible de faire une initialisation statique. Voir la documentation de gcc à ce sujet.

Publicités

Une Réponse

  1. Pingback: struct : déclarer des types et des variables en C | Pierre Gradot

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s