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 :

Problème de compréhension de type de variables d'une structure


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2020
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2020
    Messages : 18
    Par défaut Problème de compréhension de type de variables d'une structure
    Bonjour j'aimerais qu'une personne m'éclaire au sujet d'une structure concernant des types de variable j'ai le code suivant que l'on m'a donné :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    typedef struct
    {
        size_t (*hash)(const void *, size_t); // size_t => unsigned integer
        int (*compare)(const void *, const void *);
        size_t length;
        size_t nb;
        size_t size;
        List list[1];
    } HashTable;
    La variable compare est un pointeur vers int, mais ce que je ne comprends pas c'est qu'elle est suivit d'un pointeur générique constant cela signifie quoi en C :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int (*compare)(const void *, const void *);
    Merci d'avance pour toutes aides !

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    compare n'est pas un pointeur sur un int, c'est un pointeur sur une fonction qui reçoit 2 paramètres et qui retourne un int. Les deux paramètres sont pointeurs sur des zones en lecture seule.

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2020
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2020
    Messages : 18
    Par défaut réponse
    Citation Envoyé par dalfab Voir le message
    Bonjour,

    compare n'est pas un pointeur sur un int, c'est un pointeur sur une fonction qui reçoit 2 paramètres et qui retourne un int. Les deux paramètres sont pointeurs sur des zones en lecture seule.
    donc si j'ai bien compris prenons cet exemple void (*print)(void *, FILE *) print est une fonction qui renvoie un pointeur générique et qui a besoin de deux paramètre un fichier et un pointeur générique

  4. #4
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    780
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 780
    Par défaut
    Non, print est un pointeur sur une fonction de type void. Mais tu as bien compris qu'elle demande deux paramètres: le premier de type void *, le second de type FILE *

    Il a trois cas à prendre en compte:
    - void (*print)(....): print est un poieur sur une fonction de type void
    - void *(print)(....): (équivalent à void *print(....)): tu déclares qu'il existe une fonction print qui renvoie une pointeur sur une donnée de type void
    - void *(*print)(....): print est un pointeur sur une fonction qui renvoie un pointeur sur une donnée de type void

  5. #5
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Je pense que le concept de pointeur de fonction t'est nouveau.
    Un pointeur ça contient l'adresse de quelque chose. Par exemple un int* ça contient l'adresse d'un entier.
    En particulier le pointeur de fonction peut stocker l'adresse d'une fonction. Donc il va "se souvenir" de la fonction tout comme un int* sert à retrouver où est un int.
    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
    int (*compare)(const void*, const void*);  // la variable de type pointeur sur fonction
     
        compare = &la_fonction;   // comme tout pointeur on doit l'initialiser avant de s'en servir
        // ou
        compare = la_fonction;
     
    // la fonction 'la_fonction' existe quelque part et a le format:
    int la_fonction( const void* p1, const void* p2 ) { // la fonction a exactement les mêmes types de paramètres et type de retour qu'indiqué dans le pointeur
        if ( ..... )
            return  +1;  // plus grand
        else if ( ..... )
            return  -1;  // plus petit
        else
            return  0;   // sont égaux
    }
     
    // plus tard, on utilise le pointeur (et comme pour tous les pointeurs on utilise l'étoile.)
        const void*  param1 = NULL;
        const void*  param2 = NULL;
        (*compare)( param1, param2 );   // Ça appelle la fonction mémorisée (donc la fonction 'la_fonction')
    // et si on avait mémorisée une autre fonction, ça l'appellerait.

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 830
    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 830
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Modaak Voir le message
    La variable compare est un pointeur vers int, mais ce que je ne comprends pas c'est qu'elle est suivit d'un pointeur générique constant cela signifie quoi en C :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int (*compare)(const void *, const void *);
    Autre explication: en C, tout a une adresse. Tes variables (ex int a, tes tableaux (ex int t[]). Il se trouve que les fonctions de ton programme possèdent aussi une adresse (pour simplifier on peut dire que c'est l'adresse dans le code où commence le code de la fonction).
    Donc dans le prototype, une fonction peut être nommée par son nom (syntaxe "standard") ou bien par le fait qu'on ne connaisse que son adresse, et dans ce dernier cas on utilise la syntaxe pointeur (étoile variable) suivie de parenthèses pour invoquer la notion "fonction".
    Et dans les parenthèses on indique les paramètres reçus par cette fonction car cela reste quand-même une fonction avec paramètres (signature).

    Donc dans int (*compare)(const void *, const void *) la variable "compare" contient l'adresse du code de la fonction donc "étoile compare" sera la fonction elle-même, fonction recevant deux pointeurs universels (void étoile) dont on ne peut pas modifier la valeur sur quoi ils pointent (const), et cette fonction retourne un int.
    Et comme les priorités placent l'étoile bien après tout le reste, il faut mettre des parenthèses à "étoile compare" pour que l'étoile soit associée à la variable "compare" et non pas au type "int".

    A noter que dans les premières version du C, les paramètres n'étaient pas indiqués. Ce pointeur de fonction aurait alors été déclaré de cette façon: int (*compare)().
    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]

  7. #7
    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,

    Moi la structure me semble bizarre surtout avec cette déclaration de tableau de taille 1 à la fin. Je pense que l'intention est d'utiliser un tableau membre flexible mais de mémoire ça se déclare sans taille. Après tout dépend de ce que représente exactement List mais c'est bizarre quand même.

  8. #8
    Membre émérite
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Par défaut
    Oui c'est bien pour avoir un membre flexible, mais c'était la syntaxe avant C99 ; il fallait alors obligatoirement spécifier une taille.
    C'est donc un code qui traîne depuis en gros 20 ans sans modifs …

  9. #9
    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
    Effectivement c'est une ancienne pratique qui s'appelait un structure hack. Voir également
    ce fil sur stack
    avec des références très intéressantes vers la faq C et surtout le C99 rationale pour qui le paragraphe 8 de la section 6.5.6 du standard C99 est suffisant pour classer cette pratique dans les comportements indéfinis

    The validity of this construct has always been questionable. In the response to one Defect Report, the Committee decided that it was undefined behavior because the array p->items contains only one item, irrespective of whether the space exists.
    , et pour cause, ce paragraphe existait déjà dans C89/90.

    Il y a aussi cette requête où on voit clairement qu'il est préférable de s'en tenir à la norme car la conformité de tel ou tel compilateur peut être renforcée sans préavis.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 17/02/2021, 07h18
  2. Réponses: 4
    Dernier message: 12/11/2009, 17h09
  3. Récupérer un type de variable par une adresse.
    Par jph_void dans le forum C++
    Réponses: 11
    Dernier message: 20/08/2007, 13h13
  4. Réponses: 4
    Dernier message: 31/07/2007, 21h52
  5. [MySQL] Récupération du type de variable d'une colonne
    Par Nephret dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 08/02/2007, 13h43

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