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 :

dereferencing void pointer


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 95
    Points : 60
    Points
    60
    Par défaut dereferencing void pointer
    Bonjour à tous,

    Je voudrais faire une fonction en C qui prend une pile (représentée par un tableau d'objets quelconques) en paramètre, en créé un 2 fois plus gros puis copie tous les éléments du 1er dans le 2eme et pour finir change le pointeur du 1er sur le 2nd. Note (la pile connait sa taille et son nombre d'éléments):

    Donc pour le tableau:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void * tab;
     
    tab = malloc(50 * sizeof(void));
    Puis la fonction:

    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
    void tab_double(pile s) {
     
        void* tempo;
        int i = 0;
     
        tempo=malloc(2 * s->taille * sizeof(void));
     
        while(i < s->nb_elem){
            tempo[i] = s->tab[i];
        }
     
        s->tab = tempo;
     
        /* LE FREE */
     
    }
    J'ai donc 2 warning "dereferencing void * pointer" ligne 9. J'ai cherché un peu sur internet le problème et je ne comprend pas bien (la plupart caste la chose).

    PS: JE NE VEUT PAS UTILISER DE REALLOC VOLONTAIREMENT.

    Merci

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Le fait est que void est un "non type" Enfin, pour être précis, un type qui représente une donnée vide. A priori, cela n'a donc pas de taille

    Si void * a bel et bien une taille, c'est parce qu'il s'agit d'un pointeur, et qu'un pointeur est une donnée numérique entière (généralement non signée) dont la taille est "suffisante pour représenter n'importe quelle adresse mémoire". Le pointeur sur void est donc une donnée qui a une taille qui permet de représenter l'adresse d'une donnée qui n'en a pas à proprement parler

    Le compilateur le sait très bien, et il te donne donc un avertissement pour te prévenir

    Ce que l'on peut faire, c'est d'office tout transtyper en char, car on a la certitude que, quelle que soit la taille des objet que l'on mettra dans le tableau / la pille, elle sera d'office un multiple de la taille d'un char (vu que sizeof(char) == 1, garanti par la norme) et que char, c'est un type qui représente "un certain nombre" de bits, clairement défini sur une architecture donnée.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 374
    Points : 23 631
    Points
    23 631
    Par défaut
    Bonjour,

    « void » n'est pas un type ordinaire : c'est plutôt une manière de dire que le type est ici inexistant, sans objet ou indéfini.

    « deferencing void pointer » signifie que tu as déclaré un pointeur void mais que tu essaies par la suite d'accéder à ce qu'il pointe via « * » alors que, par définition, on ne sait pas ce qu'il pointe et on ne peut donc pas aller en récupérer la valeur.

    malloc() renvoie un pointeur void * par défaut parce que c'est une fonction générique qui sert à allouer de la mémoire pour n'importe quel usage. L'espace à allouer est mesuré en char, donc en octets dans la majorité des cas. Il faut donc affecter sa valeur à un pointeur correctement typé, soit ici celui de s->tab.

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    malloc() renvoie un pointeur void * par défaut parce que c'est une fonction générique qui sert à allouer de la mémoire pour n'importe quel usage. L'espace à allouer est mesuré en char, donc en octets dans la majorité des cas. Il faut donc affecter sa valeur à un pointeur correctement typé, soit ici celui de s->tab.
    Je dirais plutôt en byte ("multiplet" en francais ) car c'est plus générique : octet contient la racine oct(o) qui signifie 8, ce qui fait que octet est d'office composé de... 8bits, par sémantique.

    C'est vrai dans la plupart des cas, mais ce n'est pas garanti (il n'y a aucune obligation à ce que les byte fassent effectivement 8bits). Byte ou "multiplet() sont des termes qui indiquent juste que c'est "le plus petit ensemble insécable de bits" que l'on trouve sur la machine, mais n'implique aucune notion quant au nombre de bits que cela représente. C'est donc plus juste, car plus "imprécis"
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 95
    Points : 60
    Points
    60
    Par défaut
    Merci de ta réponse koala01,

    J'ai tout compris sur le plan théorique, en revanche en pratique je n'y arrive pas.
    Bon je pense que du coup il me faut mettre un sizeof(char) mais après au niveau de la ligne 9 je fais comment pour récupérer des objets qui n'ont pas de type prédéfini ?

    EDIT: Vos messages sont passés entre temps.

    @Obsidian : merci de t'interessé au sujet. Le truc c'est que mon s->tab est un tableau d'objets quelconques donc void * lui aussi non ?

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Halo2550 Voir le message
    Merci de ta réponse koala01,

    J'ai tout compris sur le plan théorique, en revanche en pratique je n'y arrive pas.
    Bon je pense que du coup il me faut mettre un sizeof(char) mais après au niveau de la ligne 9 je fais comment pour récupérer des objets qui n'ont pas de type prédéfini ?
    Le plus facile, c'est de transmettre également la taille de tes objets à la fonction (le résultat de sizeof(le type qui t'intéresse)). Parce que cette taille est exprimée en char (en byte), et que si tu fais nombre d'élément * taille exprimée en char, tu obtiendra, forcément, le nombre de caractères qui devront effectivement:
    1. être alloué dynamiquement
    2. être copié d'un endroit à l'autre
    Et ce, quel que soit le type des éléments que tu auras dans ton tableau

    Ta fonction devrait donc être modifiée pour prendre une forme qui ressemblerait à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void tab_double(pile s, size_t sizeOfElement) {
     
        void* tempo;
        int i = 0;
     
        tempo=malloc(2 * s->taille * sizeof(char) * sizeOfElement);
        // tu pourrais utiliser plutot memcpy(tempo, s->tab, sizeOfElement * s->nb_elem);
        // comme cela tu copie tout "en une seule instruction" ;)
        while(i < s->nb_elem * sizeOfElement){
        // ...
    EDIT : note que le * sizeof(char) n'est pas obligatoire, vu que c'est une valeur garantie valoir 1
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 95
    Points : 60
    Points
    60
    Par défaut
    Alors désolé je nage un peu mais là pour moi on ne fais que repousser le problème à la fonction appelante. Qu'est-ce que je vais mettre dans le paramètre sizeOfElement ?

    De base je fais une pile pouvant contenir toute sorte d'objet mais je ne sais pas ce qui va être mis dedans.

    Je penses que toi tu est parti sur le fait que à la fonction appelante je met des objets du même type dans la pile mais pas forcément.

  8. #8
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Le descripteur de pile (*s) doit mémoriser la taille de la pile actuelle en bytes (peut être est-ce s->taille ?) et l'utiliser pour faire un memcpy() pour dupliquer le contenu de la pile.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Halo2550 Voir le message
    Alors désolé je nage un peu mais là pour moi on ne fais que repousser le problème à la fonction appelante. Qu'est-ce que je vais mettre dans le paramètre sizeOfElement ?

    De base je fais une pile pouvant contenir toute sorte d'objet mais je ne sais pas ce qui va être mis dedans.

    Je penses que toi tu est parti sur le fait que à la fonction appelante je met des objets du même type dans la pile mais pas forcément.
    Ben, à vrai dire, par définition, les collections d'objets sont toujours sensées être des collections d'objet de types identique (ou, au pire, d'objets "compatibles").

    Tu peux avoir une collection de voitures, éventuellement une collection de véhicules qui mélangent des voitures et des bâteaux, mais tu ne peux pas trouver dans une même collection des véhicules,des végétaux (arbre, fleurs, chêne, hêtre) et des outils (perceuse, tournevis, marteau).

    Tu peux, éventuellement te dire que tu ne sais pas ce que ta collection va gérer, mais que tu sais par contre très bien comment ta collection va gérer les différents éléments (une pile reste une pile, que ce soit une pile d'assiettes, de livre ou de boites )

    Mais, à partir du moment où tu as décider de gérer tes objets sous la forme d'une pile, ou bien, tu gères une pile de pointeurs, vu que la taille d'un pointeur est clairement définie, ou bien tu dois gérer une pile d'objets particuliers, car la taille des éléments dépendra de la taille du type que tu veux mettre dans la pile
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 95
    Points : 60
    Points
    60
    Par défaut
    Oui justement koala01 je me suis embrouillé je veut une pile (tableau) de pointeurs mais qui eux peuvent pointer sur des objets de types différents. Genre le 1er élément sera un pointeur sur un int puis le 2eme un pointeur sur un char par exemple.

    C'est bien faisable ca non ?

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Comme je te l'ai dit, si les éléments de ta pile sont des pointeurs, que ce soit des pointeurs vers des int, des pointeurs vers des char ou des pointeurs vers de StructVerryComplicated, ce seront toujours des pointeurs et la taille de ceux-ci sera toujours la même.

    Donc, oui, c'est possible, et tu peux même envisager d'utiliser sizeof(void *) pour déterminer la taille par laquelle tu dois multiplier le nombre d'élement afin de savoir le nombre de byte qu'il faut recopier.

    Par contre, je te déconseille fortement de mélanger des pointeurs sur int et des pointeurs sur char (ou meme des pointeurs sur int et des pointeurs sur float / double) dans une seule et même collection, car on en revient au même problème que celui qui se poserait si tu essayais de mélanger des végétaux, des véhicules et des outils dans une collection : comment faire pour déterminer si tu dois manipuler l'objet pointé comme une chaine de caractères, comme un entier (en sachant, par exemple, que la division provoquera un reste) ou comme un float / double en sachant que la division sera sans doute "imprécise"

    Si ce ne sont que des pointeurs sur int, que des pointeurs sur char ou que des pointeurs sur float, ce problème ne se pose pas
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Modifier un void pointer
    Par Paltoquet dans le forum C
    Réponses: 12
    Dernier message: 30/12/2014, 14h47
  2. forward declaration et error: dereferencing pointer
    Par vincent.mbg dans le forum C
    Réponses: 4
    Dernier message: 15/06/2010, 12h57
  3. dereferencing pointer to incomplete type
    Par Newgaia dans le forum Débuter
    Réponses: 2
    Dernier message: 19/04/2009, 19h00
  4. Réponses: 3
    Dernier message: 12/01/2007, 10h25
  5. dereferencing pointer....
    Par vince3320 dans le forum C
    Réponses: 19
    Dernier message: 12/10/2005, 20h46

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