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 :

warning sur conversion de pointeurs


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 5
    Par défaut warning sur conversion de pointeurs
    Bonjour,
    Voici un bout de code qui me renvoie un warning ("compiler dependent") sur la conversion d'un pointeur de fonction en pointeur de données. Ici, il ne faut pas prendre cet exemple pour argent comptant. Ma question est plus générale : Comment convertir "proprement" des pointeurs quels qu'ils soient ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main(void)
    {
        unsigned char *MyPointer;
        MyPointer = (unsigned char*) &main;
        (void) printf("%.2X\n", *MyPointer);
        return 0;
    }
    merci d'avance

  2. #2
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Pour les pointeurs autres que pointeurs de fonctions, la seule conversion parfaitement sure est void * <-> type *. Pour les autres conversions, il faut savoir ce que l'on fait.
    Pour les pointeurs de fonctions, il n'existe pas de pointeur generique.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 5
    Par défaut
    si je vous comprends bien, je ne peux pas éviter le warning ?
    Là où je ne saisis pas bien la chose, c'est en quoi ce genre de conversions dépendent du compilateur ? Que peut-il se passer si on change de compilo ?

  4. #4
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Tu es dans le domaine du comportement indefini (ou peut-etre implementation-dependent, je ne suis pas sur), donc tout peut arriver, y compris un comportement normal.
    Pour corriger le code que tu postes, il faut declarer MyPointer comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int (*MyPointer)(void);
    et tout ira bien.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 5
    Par défaut
    ok. Le problème est que si je déclare MyPointer comme pointeur de fonction, si je veux ensuite qu'il pointe vers une autre fonction qui n'a pas le même prototype que 'main', je suis marron. Mon idée ici était de disposer d'un pointeur générique (void* ou char*) utilisable par exemple dans une fonction qui ne se soucie pas du type de pointeur qui lui est transmis. Cette transmission est sous la responsabilité de l'utilisateur. Mais s'il y a des warnings à chaque fois, c'est sujet à questionnements de la part de ces dits utilisateurs (alors même qu'il n'y a pas d'erreur).
    Donc :
    Si je déclare MyPointer en void*, j'ai le warning quoiqu'il arrive.
    Si je déclare MyPointer en int(*)(void), je ne peux pointer que vers des fonctions avec un tel proto.
    C'est une restriction propre à la norme C99 peut-être. Si le compilo respecte la norme, y a pas de souci et dans le cas contraire, comportement indéfini...enfin, je dis ça, je suis peut-être complètement à côté de la plaque

  6. #6
    Membre émérite
    Avatar de Pouet_forever
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    671
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 671
    Par défaut
    Ce n'est pas propre au C99. Regarde le warning que j'ai, ça devrait t'éclairer un peu plus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    warning: ISO C forbids conversion of function pointer to object pointer type
    ISO C ne fait pas référence à C99 !

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 5
    Par défaut
    ha ok. Donc, c'est une restriction de l'ISO...donc, en théorie, je n'ai pas le droit de le faire si je veux respecter la norme. Et bien, j'ai appris un truc Donc :
    Soit je repense mon programme pour qu'il évite ce non respect de la norme.
    Soit je vie avec et j'assume le fait de skier en hors piste.

    merci pour vos réponses.

  8. #8
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Comme je l'ecris plus haut, il n'y a pas de pointeur de fonction generique, donc tu es en effet "marron".
    Il y a une solution cependant, voir ici.
    D'autres solution incluent l'utilisation d'une fonction wrapper qui se charge des differences de prototype.

    Je te conseille de lire cette reponse de Eric Sosman dans c.l.c, c'est un excellent resume du probleme et de ses solutions.

  9. #9
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    désolé de vous contredire, mais là il ne s'agit pas en l'occurence d'un pointeur de fonction...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int main ( void )
    {
        unsigned char *MyPointer;
        MyPointer = (unsigned char*) &main;
    mais d'un bête cast d'un type éventuellement (preque tout le temps) supérieur vers un type inférieur...




    Dans ce cas, quel que soit le type, le compilo protestera en warning...

    Que cela soit un pointeur de fonction ou non...

  10. #10
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Citation Envoyé par DaZumba Voir le message
    Comme je l'ecris plus haut, il n'y a pas de pointeur de fonction generique
    En fait, pour éviter les mauvaises interprétations, tous les types "pointeur de fonction" sont génériques. Tout pointeur de fonction peut être converti, sans cast, en un pointeur de fonction de type différent. C'est la conversion de pointeur d'objet en pointeur de fonction et vice-versa qui n'est pas forcément faisable. La norme ne l'interdit pas, mais ce n'est pas requis non plus. Personnellement, je ne connais pas de système sur lequel cette conversion n'est pas faisable (du moins à la compilation).

    Citation Envoyé par DaZumba
    Il y a une solution cependant, voir ici.
    Il ne faut JAMAIS utiliser les unions dans un but pareil, si on veut être portable. Le cast de pointeur de fonction <-> pointeur d'objet est beaucoup plus portable que cette solution là.

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 5
    Par défaut
    @Dazumba : merci pour les docs, ça m'a permis de faire quelques tests. Par contre, je ne sais pas ce que veut dire :

    On some machines, function addresses can be very large, bigger than any data pointers
    dommage qu'il n'ait pas détaillé ce propos, je suis curieux de savoir de quoi il s'agit.

    Par contre, j'ai essayé de bricoler des trucs à partir des void(*)(void), et j'ai obtenu ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    int MyFunction(int MyParam) {
       MyParam++;
        return MyParam;
    }
     
    int main(void)
    {
        char * MyPointer;
        MyPointer = (char*) (ULONG_PTR) &MyFunction;
    	(void) printf("the byte located at %#x is : %#.2x\n", MyPointer, *MyPointer);
    	return 0;
    }
    Le ULONG_PTR , que j'ai collé entre un int(*)(int) et un char* m'évite le warning et j'obtiens le résultat escompté ! (ne me demandez pas pourquoi j'évite le warning avec cela)

    @souviron34 : &main, c'est un pointeur de fonction, non ?

    cast d'un type éventuellement (preque tout le temps) supérieur vers un type inférieur...
    que signifie 'type supérieur' et 'type inférieur' ? Un pointeur reste finalement une adresse mémoire (codée sur 32 bits ou 64 bits), que ce soit un pointeur de fonction , de char ou de je ne sais quoi.

  12. #12
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par beatrix2004 Voir le message
    que signifie 'type supérieur' et 'type inférieur' ? Un pointeur reste finalement une adresse mémoire (codée sur 32 bits ou 64 bits), que ce soit un pointeur de fonction , de char ou de je ne sais quoi.
    là tu assignes à un pointeur qui pointe vers un char (admettons 8 bits) un pointeur qui pointe vers 32 (en général).

    Le compilo t'avertit que ce n'est pas équivalent...

    Tu as donc bien un pointeur, mais la valeur pointée n'a plus de sens...


    ps : &main, c'est un pointeur de fonction, mais avant cela c'est un pointeur sur un int..

  13. #13
    Expert confirmé
    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
    Par défaut
    souviron34 :
    ps : &main, c'est un pointeur de fonction, mais avant cela c'est un pointeur sur un int..
    &main, c'est un pointeur de fonction, point c'est tout.

  14. #14
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    tu aurais le même warning si tu faisais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int toto ;
    char *MyPtr ;
     
    MyPtr = (char *)&toto ;

  15. #15
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    En fait, pour éviter les mauvaises interprétations, tous les types "pointeur de fonction" sont génériques. Tout pointeur de fonction peut être converti, sans cast, en un pointeur de fonction de type différent
    Enfin, pratiquement sur tous les compilos C, tu auras un warning... (et en C++, une erreur, il me semble).
    Mon idée ici était de disposer d'un pointeur générique (void* ou char*) utilisable par exemple dans une fonction qui ne se soucie pas du type de pointeur qui lui est transmis.
    Mais après, comment appelles-tu la fonction pointée? Le C standard ne permet pas d'appeler dynamiquement n'importe quelle fonction.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Réponses: 4
    Dernier message: 09/01/2013, 15h30
  2. Réponses: 2
    Dernier message: 03/09/2010, 08h39
  3. Warning sur pointeur 64bits
    Par Gui13 dans le forum C
    Réponses: 1
    Dernier message: 13/12/2009, 11h21
  4. Réponses: 10
    Dernier message: 03/02/2005, 13h09
  5. Réponses: 5
    Dernier message: 05/06/2004, 13h12

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