Petite présentation de sys/queue.h
Dans vos programmes C, il arrive très fréquemment d'utiliser des listes chaînée (de toutes sortes), afin de ne pas avoir à recréer le monde à chaque fois vous pouvez utiliser les macros super pratiques de queue(3). Voici une petite introduction à l'utilisation de sys/queue.h avant d'aller se plonger dans le man pour aller plus loin.
Avec sys/queue.h , vous pouvez manipuler facilement quatres sortes de listes :
- Listes simplement chainées (SLIST) de type pile
- Listes doublement chainées (LIST) de type pile
- Listes simplement chainées (STAILQ) de type file
- Listes doublement chainées (TAILQ) de type file
Voici un exemple de SLIST :
Le header :
#ifndef HEADER_H #define HEADER_H #include <sys/queue.h> typedef struct MaStruct { /* ici on met nos elements par exemple : */ char *str; /* * On déclare notre liste avec SLIST_ENTRY qui est equivalente à * struct { struct MaStruct *sle_next; } next; */ SLIST_ENTRY(MaStruct) next; } MaStruct; #endif /* HEADER_H */
Ensuite voyons comment manipuler cette liste :
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "header.h" int main(void) { /* SLIST_HEAD crée une variable pour acceder à notre liste */ SLIST_HEAD(, MaStruct) head; /* on crée un element MaStruct */ MaStruct *p; /* On l'initialise à NULL */ SLIST_INIT(&head); p = malloc(sizeof(*p)); p->str = malloc(sizeof(char) * 10); strcpy(p->str, "blah"); /* On insere p dans la SLIST */ SLIST_INSERT_HEAD(&head, p, next); /* On empile un deuxième element */ p = malloc(sizeof(*p)); p->str = malloc(sizeof(char) * 10); strcpy(p->str, "blu"); SLIST_INSERT_HEAD(&head, p, next); /* * Il est très facile de parcourir la liste * que ce soit pour du traitement ou de * la libération de mémoire */ SLIST_FOREACH(p, &head, next) { /* ici p est l'element courant */ printf("element : %s\n", p->str); } /* exemple de libération */ while (!SLIST_EMPTY(&head)) { p = SLIST_FIRST(&head); SLIST_REMOVE_HEAD(&head); free(p->str); free(p); } return 0; }
Parmis les macros interessantes pour les SLIST il y a :
SLIST_FIRST(&head); /* renvoie la tête de liste */ SLIST_REMOVE_HEAD(&head, next); /* supprime la tete de liste */ SLIST_EMPTY(&head); /* renvoie vrai si la liste est vide */
Ben entendu, il y a beaucoup plus de possibilités avec LIST et TAILQ... Mais globalement vous devriez avoir compris le principe.
La lecture de sys/queue.h devrait vous éclairer pour comprendre comment marchent toutes ces macros, c'est assez facile à comprendre si vous avez (comme moi) un niveau moyen en C.
Voyez aussi ce papier d'iMil.
Previous postNouveau blog |
Next postSpamd ourgl |
Comments: 2
Salut, en effet il y a une erreur. Je corrige ça, merci :-)
Bonjour,
L'exemple de "nettoyage" de la liste n'est pas correct:
SLIST_FOREACH(p, &head, next) { / ici p est l'element courant / printf("element : %sn", p->str); free(p->str); free(p); }
SLIST_FOREACH fait: for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
Le pb c'est que le free(p) va libérer l'espace occupé par p, mais ensuite à l'itération suivante, on fait p = p->next.sle_next; ...


2