IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Utilisation triple pointeur


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 256
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 256
    Par défaut Utilisation triple pointeur
    bonsoir,

    Je cherche à comprendre le fonctionnement de triple pointeur avec notamment la structure namelist de la fonction scandir.

    J'arrive à exploiter le retour, namelist sera en fait un tableau de structure dirent.

    Pourquoi ça utilise un triple pointeur ?

    Je cherche à reproduire le fonctionnement de scandir, je bloque sur la création du tableau de pointeurs namelist.

    Tout ça manque un peu de clarté pour moi.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 832
    Billets dans le blog
    1
    Par défaut
    Salut
    Citation Envoyé par chrtophe Voir le message
    Tout ça manque un peu de clarté pour moi.
    Le point de départ à bien comprendre, et à garder toujours à l'esprit, c'est que que toute fonction qui modifie un truc reçoit l'adresse de ce truc, adresse qu'elle stocke dans un "truc étoile". La règle est simple: je modifie un truc, je rajoute alors "étoile" dans le type du paramètre qui reçoit ce truc.

    Prenons un exemple simple: une fonction qui met un int à 0. Elle modifie cet int, elle reçoit l'adresse de cet int qu'elle stocke alors dans un int étoile.
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int raz(int *pt) {
    	*pt=0;
    }
     
    int main() {
    	int xxx=123;
    	raz(&xxx);
    	printf("xxx=%d\n", xxx);
    }

    Que se passe-t-il si le truc à modifier est déjà un pointeur (donc qqchose ayant déjà une étoile dans son type) ? Rien ne change dans le principe. Simplement la fonction reçoit l'adresse de ce pointeur, adresse qu'elle stockera dans un pointeur de pointeur => un truc étoile étoile
    Exemple: une fonction qui reçoit une string et qui va positionner un pointeur de char (un char étoile donc) sur le premier caractère précis de ladite string. Elle modifie un "char étoile", elle va recevoir l'adresse de ce "char étoile", adresse qu'elle stockera dans un "char étoile étoile".
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void find_char(char *s, char c, char **res) {
    	char *pt;
    	for (pt=s; *pt != c && *pt != '\0'; pt++);
    	if (*pt == c) (*res)=pt;
    }
     
    int main() {
    	char *s="Hello World";
    	char *pt;
    	find_char(s, 'W', &pt);
    	printf("pt=%s (offset=%d)\n", pt, pt-s);
    }

    Ici c'est encore exactement la même chose... mais un cran au dessus. La fonction devant modifier un struct dirent ** devra recevoir son adresse, adresse qu'elle stockera dans un struct dirent ***. Et pourquoi elle doit modifier un double étoile ? La première étoile symbolise la notion de tableau, et la seconde étoile symbolise le pointeur de type struct dirent. Autrement dit, la fonction va créer un tableau de pointeurs, chaque pointeur pointant vers une structure struct dirent. Encore autrement dit, la fonction va créer le tableau des répertoires trouvés lors du scan.
    Exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>
     
    int main() {
    	struct dirent **namelist;
    	int n;
     
    	n = scandir(".", &namelist, 0, alphasort);
    	printf("nb trouvés: %d\n", n);
    	while (n--) {
    		printf("%s (0x%04x)\n", namelist[n]->d_name, namelist[n]->d_type);
    		free(namelist[n]);
    	}
    	free(namelist);
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Un pointeur est une variable qui pointe sur un truc.
    Un pointeur de pointeur est une variable qui pointe sur un pointeur (qui lui-même pointe sur un truc).
    etc...

    En C, un pointeur peut aussi être utilisé pour représenter un tableau.
    Donc char* : un pointeur sur char ou un tableau de char
    char** : un pointeur sur char* ou un tableau de char*
    etc aussi

    En C c'est aussi le moyen d'avoir des paramètres out.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    667
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 667
    Par défaut
    Salut,

    Citation Envoyé par chrtophe Voir le message
    Je cherche à comprendre le fonctionnement de triple pointeur avec notamment la structure namelist de la fonction scandir.

    J'arrive à exploiter le retour, namelist sera en fait un tableau de structure dirent.

    Pourquoi ça utilise un triple pointeur ?
    Parce-que c'est la fonction scandir qui s'occupe d'allouer la mémoire pour namelist.

    Voici une declaration de départ, la variable de base, un tableau de structure dirent:
    struct dirent *namelist, autrement "dit" struct dirent namelist[] (juste pour la symbolique, car c'est pas tout à fait vrai)

    Voilà ce que construit scandir dans le tas :
    struct dirent namelist_tas[].

    Et donc comment faire pour que namelist pointe sur namelist_tas?
    Et bien il faut une indirection supplémentaire, c.-à-d. que namelist doit être un pointeur, autrement dit, namelist doit être déclaré struct dirent (*namelist)[], en somme struct dirent **namelist.

    Ne reste plus qu'à passer l'adresse de namelist à scandir: &namelist.

    On récapitule. On passe une adresse à scandir, scandir reçoit un pointeur.
    Et si cette adresse est un pointeur de pointeur, qu'est censée recevoir scandir ?

  5. #5
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 256
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 256
    Par défaut
    Bonsoir,

    Merci pour vos retours.

    J'utilise sans problème et est bien notion pour les chaines de l'utilisation soit sous forme de pointeur, soit sous forme de tableau de char. J'avais zappé le fait qu'on pouvait faire un tableau avec autre chose que du char.

    Il me reste à gérer l'allocation de mon tableau de char et le retourner dans le namelist. Je risque de cafouiller encore un peu. Si je m'en sors pas, je reviendrais vers vous. De mes premiers tests, si je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    struct dirent **lecture;
    printf("adr lecture avant scandir :% %p\n",&lecture,lecture);
    scandir(".",&lecture,NULL,NULL);
    printf("adr lecture apresscandir :% %p\n",&lecture,lecture);
    Je vois bien qu'il y a allocation (nil) remplacé par une adresse.
    Il me reste à voir comment exploiter le contenu de cette adresse, soit c'est le tableau de structures dirent, soit c'est sa première entrée, j'ai pas eu le temps d'aller plus loin.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    https://man7.org/linux/man-pages/man3/scandir.3.html
    The scandir() function returns the number of directory entries
    selected. On error, -1 is returned, with errno set to indicate
    the cause of the error.
    Donc tu sais combien de résultats tu as, et le résultat est un tableau de pointeurs eux-mêmes alloués et qu'il faudra libérer, en plus de libérer le tableau.
    Les exemples d'utilisation sont légion sur internet. La doc en montre elle-même un simple.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 256
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 256
    Par défaut
    Oui, j'arrive à l’utiliser,

    J’essaye de reproduire le fonctionnement de scandir, en gros créer ma propre fonction scandir. rien de vraiment utile, c'est formateur, la preuve, je suis obligé de me mettre sur cette histoire de triple pointeur ...
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Le fonctionnement interne de scandir est une multitude de malloc pour y parvenir.
    L'implémentation de base ressemble sûrement à quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int scandir(const char* path, struct Dir*** out)
    {
      int nbDir = xxx; // Une façon quelconque de trouver le nombre de résultats, certainement des fonctions systèmes
      *out = malloc(nbDir * sizeof(Dir*)); // On alloue le pointeur reçu pour lister les résultats
      for (int i = 0; i < nbDir: ++i)
      {
        (*out)[i] = malloc(sizeof(Dir)); // On alloue chaque résultat dans la liste
        (*out)[i]->fillMe();
      }
      return nbDir;
    }
    Après ils ont des fioritures pour filtrer ou ordonner les résultats en interne.
    Tu peux même sûrement trouver des sources qui l'implémente quelque part.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 832
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    Il me reste à voir comment exploiter le contenu de cette adresse, soit c'est le tableau de structures dirent, soit c'est sa première entrée, j'ai pas eu le temps d'aller plus loin.
    Le nom d'un tableau c'est en même temps l'adresse de sa première entrée. Et chaque entrée c'est un "struct dirent".

    Déjà il te faut récupérer la valeur renvoyée par scandir() car cette valeur représente le nb de dossiers trouvés, donc par ricochet le nb d'éléments du tableau.
    Et donc une fois que tu as le départ du tableau et son nb d'éléments...

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>
     
    int main() {
    	struct dirent **lecture;
    	int n, i;
     
    	n=scandir(".",&lecture,NULL,NULL);
    	printf("nb trouvés: %d\n", n);
    	for (i=0; i < n; i++)
    		printf("%s (0x%04x)\n", lecture[i]->d_name, lecture[i]->d_type);
    }
    Tu n'oublieras pas, une fois que tu as fini d'utiliser ton tableau, de le libérer de ses allocations (cf mon précédent exemple).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. Réponses: 14
    Dernier message: 22/04/2006, 21h59
  2. Optimiser l'utilisation des pointeurs
    Par progfou dans le forum C
    Réponses: 65
    Dernier message: 10/03/2006, 11h49
  3. Réponses: 6
    Dernier message: 21/02/2006, 16h47
  4. Utilisation de pointeurs
    Par renard s dans le forum Débuter
    Réponses: 7
    Dernier message: 08/12/2005, 08h18
  5. Utilisation de Pointeurs dans API windows
    Par Drooxy dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 13/03/2003, 22h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo