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

  1. #1
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    14 158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 14 158
    Points : 32 346
    Points
    32 346
    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 la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 881
    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 : 8 881
    Points : 24 401
    Points
    24 401
    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 «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    6 672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 6 672
    Points : 30 451
    Points
    30 451
    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 confirmé
    Femme Profil pro
    ..
    Inscrit en
    décembre 2019
    Messages
    223
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 91
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : décembre 2019
    Messages : 223
    Points : 491
    Points
    491
    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
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    14 158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 14 158
    Points : 32 346
    Points
    32 346
    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 la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    6 672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 6 672
    Points : 30 451
    Points
    30 451
    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
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 881
    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 : 8 881
    Points : 24 401
    Points
    24 401
    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 «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  8. #8
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    14 158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 14 158
    Points : 32 346
    Points
    32 346
    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 la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    6 672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 6 672
    Points : 30 451
    Points
    30 451
    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.

  10. #10
    Expert éminent
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    3 829
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 3 829
    Points : 8 573
    Points
    8 573
    Par défaut
    je pense que le code de @Bousk est 1 peu trop scolaire : on ne travaille pas avec 1 triple pointeur, on n'a pas besoin d'1 indice de tableau, pas de gestion d'erreurs.

    Je vois plus 1 code comme cela (attention il peut être erroné )

    Code : 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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    int scandir(const char* path, struct dirent*** parray) {
        int nb_directories;
     
        nb_directories = give_list_directories();
     
        if (nb_directories != -1) {
            struct dirent** array;
     
            array = malloc(nb_directories * sizeof(struct dirent*));
     
            if (array != NULL) {
                int directory
                unsigned char has_no_error;
     
                (*parray) = array;
     
                for (has_no_error=1, directory=nb_directories; (has_no_error && (directory > 0)): --directory, ++array) {
                    (*array) = malloc( sizeof(struct dirent) );
     
                    if ((*array) != NULL) {
                        array->fillMe( yield_one_directory() );
                    } else {
                        has_no_error = 0;
                    }
                }
     
                if (!has_no_error) {
                    nb_directories = -1;
    //              XXX TODO: supprimer tous les dossiers déjà alloués
                    free(array);
                    (*parray) = NULL;
                }
            } else {
                nb_directories = -1;
                (*parray) = NULL;
            }
        } else {
            (*parray) = NULL;
        }
     
        return nb_directories;
    }

  11. #11
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    14 158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 14 158
    Points : 32 346
    Points
    32 346
    Par défaut
    je pense que le code de @Bousk est 1 peu trop scolaire
    C'est comme à l'école, des fois il faut un peu de temps pour comprendre et avoir le déclic.

    Mais je pense que ton exemple avec (*parray) = array; va me débloquer.

    Je vous reviens quand j'ai eu le temps de tester.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  12. #12
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 881
    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 : 8 881
    Points : 24 401
    Points
    24 401
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par foetus Voir le message
    je pense que le code de @Bousk est 1 peu trop scolaire : on ne travaille pas avec 1 triple pointeur, on n'a pas besoin d'1 indice de tableau, pas de gestion d'erreurs.
    Ah? C'est la partie où chacun propose sa petite solution?

    Donc la mienne dans laquelle je fais le traitement en une seule passe. En effet, les autres solutions commencent par compter pour savoir combien allouer (donc deux passes)...
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h>
     
    #define SZ_ALLOC		(10)
    int myScandir(char *name, struct dirent ***res) {
    	// Ouverture dossier
    	DIR *dir;
    	if ((dir=opendir(name)) == NULL) return -1;
     
    	// Traitement du dossier
    	size_t sz=0;
    	size_t nb=0;
    	struct dirent **tmp;
    	struct dirent *current;
     
    	// Lecture du dossier ouvert
    	(*res)=NULL;
    	while ((current=readdir(dir)) != NULL) {
    		// Besoin d'espace ?
    		if (nb == sz) {
    			// Agrandissement espace (pour le premier, comme "*res" est NULL, realloc se comporte comme un simple malloc)
    			sz+=SZ_ALLOC;
    			tmp=realloc(*res, sz * sizeof(*tmp));
     
    			// Souci alloc ?
    			if (tmp == NULL) goto nettoyage;
     
    			// Allocation réussie
    			(*res)=tmp;
    		}
     
    		// Allocation pour dossier en cours
    		(*res)[nb]=malloc(sizeof(*current));
    		if ((*res)[nb] == NULL) goto nettoyage;
     
    		// Récupération dossier en cours (qui est en mémoire statique)
    		memcpy((*res)[nb], current, sizeof(*current));
     
    		// On a un dossier de plus
    		nb++;
    	}
     
    	// Tout a été traité
    	closedir(dir);
    	return nb;
     
    	nettoyage:
    	// Ici gestion de la merde - Il faut nettoyer ce qui a été alloué
    	// Attention, il n'y a eu que (au max) "nb" allocations réussies (le dernier (*res)[nb] pouvant être NULL ce qui ne dérangera pas le free())
    	// La variable "sz" ne servant plus à rien servira d'indice de boucle
    	for (sz=0, tmp=(*res); sz < nb; sz++, tmp++) free(*tmp);
    	free(*res);
    	return -1;
    }
     
    int main(void) {
    	struct dirent **namelist;
    	int n;
     
    	n = myScandir(".", &namelist);
    	printf("nb dir: %d\n", n);
    	while (n--) {
    		printf("%s (0x%04x)\n", namelist[n]->d_name, namelist[n]->d_type);
    		free (namelist[n]);
    	}
    	free (namelist);
    }

    Citation Envoyé par Bousk Voir le message
    int nbDir = xxx; // Une façon quelconque de trouver le nombre de résultats, certainement des fonctions systèmes
    Hé non mon grand, malheureusement il te faut te coltiner le comptage à la main. opendir+readidir+closedir (à moins qu'on puisse faire un rewind quelconque). On aurait pu tenter le nb de liens du dossier parent malheureusement ce nb de liens ne compte que le nb de sous-dossiers (et non le nb total de fichiers) or scandir renvoie tout le contenu du dossier traité.
    Donc pas de magic system

    Citation Envoyé par chrtophe Voir le message
    Mais je pense que ton exemple avec (*parray) = array; va me débloquer.
    Encore un indice pour détecter une erreur éventuelle: quel que soit le nb d'étoiles de ton pointeur dans ta fonction (exemple comme ici struct dirent ***res à trois niveaux), tu ne dois jamais voir écrit dans ta fonction res=qqchose car dans ce cas tu modifies une variable locale, variable perdue quand la fonction se termine. Dans toute affectation, il y aura toujours au-moins une étoile à gauche de l'affectation (cf tous mes exemples précédents à une, deux ou trois étoiles).
    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

  13. #13
    Expert éminent
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    3 829
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 3 829
    Points : 8 573
    Points
    8 573
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ah? C'est la partie où chacun propose sa petite solution?
    non c'était pour montrer l'arithmétique des pointeurs dans la boucle for ... et ainsi éviter d'utiliser le triple pointeur paramètre - juste 1 tableau de pointeurs en local, ce qui est + parlant à mon sens.
    Ce que toi et @Bousk n'avaient pas fait.

    Et aussi pour dire que lorsqu'on est débutant en C, il y a 1 fantasme pointeur en mal (crainte/ appréhension/...) ou en bien - vouloir 1 pointeur avec X (X > 4) indirections (par exemple int****** super;)
    Mais dans la vrai vie, il n'y aura qu'au plus que des triples pointeurs, doubles pointeurs majoritairement (corrigez-moi si je me trompe et à moins par exemple de concevoir 1 structure de données "tordue"/ 1 diablerie)
    1) Et le plus d'indirections, c'est pour le passage de paramètre entrée et entrée/ sortie (comme l'a dit @Bousk)
    Et même dans ce cas, on peut créer 1 variable locale avec 1 indirection en moins pour travailler avec (mon exemple et comme l'a dit @Sve@r)
    Et aussi dans ce cas, ce paramètre qui a 1 indirection en plus c'est parce qu'on prend son adresse - &X, pour pouvoir le modifier (comme l'a dit @kaitlyn)

    Il y a 1 autre technique : passer juste le bon type (dans ton cas 1 double pointeur struct dirent** array et retourner 1 pointeur alloué sur le tas (comme la fonction malloc)

    2) Souvent lorsqu'1 débutant voit 1 pointeur, il pense malloc. Mais en réalité, ce n'est pas vrai dans la majeur partie des cas - c'est juste 1 adresse, ce qui crée 1 indirection de + (comme l'a dit @kaitlyn)
    C'est 1 peu comme l'agrégation/ composition versus l'héritage. Tous les débutants veulent faire de l'héritage

  14. #14
    Responsable Systèmes


    Homme Profil pro
    Technicien maintenance
    Inscrit en
    août 2011
    Messages
    14 158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : août 2011
    Messages : 14 158
    Points : 32 346
    Points
    32 346
    Par défaut
    à moins qu'on puisse faire un rewind quelconque
    Il y a une fonction rewinddir.

    Après, faire un premier scan pour compter les entrées ou faire un realloc, je sais pas ce qui est le mieux, au niveau temps à mon avis c'est kifkif. J'aime pas trop le realloc mais je suis pas sûr que ce soit techniquement justifié.
    De toute façon, faut déjà que je gère correctement cette histoire de triple pointeur.


    2) Souvent lorsqu'1 débutant voit 1 pointeur, il pense malloc. Mais en réalité, ce n'est pas vrai dans la majeur partie des cas - c'est juste 1 adresse, ce qui crée 1 indirection de + (comme l'a dit @kaitlyn)
    C'est effectivement un peu mon cas.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutoriels/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  15. #15
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 881
    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 : 8 881
    Points : 24 401
    Points
    24 401
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    Après, faire un premier scan pour compter les entrées ou faire un realloc, je sais pas ce qui est le mieux, au niveau temps à mon avis c'est kifkif. J'aime pas trop le realloc
    Un des soucis du realloc, c'est que s'il n'a pas la place d'agrandir, alors il alloue ailleurs puis déplace l'ancienne zone vers la nouvelle. Si tu fais du realloc de structures de 300Mo, ce déplacement prendra un certain temps (voire un temps certain).
    Mais ici, l'allocation/réallocation ne concerne qu'un tableau d'adresses !!! Même si le truc monte à 10000 adresses (ce qui signifie donc 10000 entrées dans le dossier traité !!!) et qu'il y a du déplacement durant les réallocations, ce déplacement ne se fera que sur les adresses, pas sur les "struct dirent". Ceci dit, j'alloue de 10 en 10 donc si le truc monte à 10000 adresses et qu'il y a déplacement à chaque réallocation ok cela fera 1000 déplacements. Bah oui, parfois le sort s'acharne.

    Citation Envoyé par chrtophe Voir le message
    De toute façon, faut déjà que je gère correctement cette histoire de triple pointeur.
    N'oublie pas qu'en réalité, tu dois juste gérer un double pointeur (le tableau de toutes les "struct dirent"). La 3° étoile c'est juste à cause de la déportation de ce tableau dans une sous-fonction

    Si je reprends mon tout premier exemple...
    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);
    }
    ... dans ma fonction "raz" je ne gère en réalité qu'un simple int, int qui se nomme "étoile pt" mais je fais totalement abstraction de "pt" que je n'ai pas à gérer en tant que variable. Si je devais écrire le "main" sans la fonction "raz", le code deviendrait...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main() {
    	int xxx=123;
    	xxx=0;
    	printf("xxx=%d\n", xxx);
    }
    ... et là on voit bien qu'on n'a en réalité qu'un int à manipuler. Ici c'est pareil. Pour utiliser "scandir" Tu te contentes de définir un struct dirent **lecture et tu passes "&lecture" à la fonction sans te poser de question. Autrement dit, tu peux faire mentalement abstraction de cette 3° étoile car en tant qu'utilisateur, toi tu ne gères qu'un truc à deux étoiles.
    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

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