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: ISO C forbids assignment between function pointer and `void *'


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juillet 2011
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 41
    Points : 40
    Points
    40
    Par défaut warning: ISO C forbids assignment between function pointer and `void *'
    *Bonjour*

    Tout est dans le titre. Si vous savez comment solutionner ça, je suis preneur.

    *Merci d'avance*

  2. #2
    Expert éminent
    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 : 38
    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
    Points : 8 389
    Points
    8 389
    Par défaut
    hook.c:7: warning: ISO C forbids assignment between function pointer and `void *'
    hook.c:8: warning: ISO C forbids assignment between function pointer and `void *'
    La norme du C n'exige pas qu'un pointeur sur un objet sur void puisse être converti en pointeur sur une fonction. Assigner un void * à un pointeur de fonction est donc une opération non portable, d'où le warning. Une manière de contourner le warning (autre que le désactiver) sans toutefois résoudre le problème de portabilité : utiliser memcpy au lieu de l'affectation.
    wrapper.c:19: warning: ISO C89 forbids specifying subobject to initialize
    wrapper.c:20: warning: ISO C89 forbids specifying subobject to initialize
    Ici la syntaxe est tout simplement non standard, il faut initialiser l'objet pendant sa définition ou alors appeler écrire une fonction d'initialisation pour être 100% conforme et donc portable.

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    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 387
    Points : 23 702
    Points
    23 702
    Par défaut
    Citation Envoyé par Melem Voir le message
    Assigner un void * à un pointeur de fonction est donc une opération non portable, d'où le warning. Une manière de contourner le warning (autre que le désactiver) sans toutefois résoudre le problème de portabilité : utiliser memcpy au lieu de l'affectation.
    Euh… je n'ai que survolé le problème, mais memcpy(), ça me paraît un peu lourd, quand même. Un simple cast ne serait-il pas justifié dans le cas présent (utilisation de dlsym()) ?

  4. #4
    Expert éminent
    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 : 38
    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
    Points : 8 389
    Points
    8 389
    Par défaut
    Je ne pense pas que l'ajout d'un cast puisse supprimer ce warning car le résultat sera le même : tu convertis toujours, par cast, un void * en pointeur de fonction, ce qui n'est pas portable. Mais c'est vrai qu'il faut tenter car je viens de me rendre compte que même le memcpy ne résout pas l'affaire. Si le cast non plus ne marche pas, et ben comme le code n'est pas portable, le seul moyen de supprimer le warning c'est de faire taire le compilateur (enlever aussi -pedantic et/ou -Wall et/ou -W).

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    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 387
    Points : 23 702
    Points
    23 702
    Par défaut
    Effectivement, si j'essaie sous GCC de transtyper « void * » vers le pointeur de fonction adéquat, j'obtiens une erreur parce que le compilateur considère que le pointeur, tout void soit-il, reste un pointeur d'objet et donc ne peut être transformé en pointeur de fonction :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main (void)
    {
        hook_t h;
     
        h._open  = (int(*)(const char *,int,mode_t))dlsym( RTLD_NEXT, "open");
        h._close = (int(*)(int))dlsym( RTLD_NEXT, "close" );
     
        return 0;
    }

    Code Shell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ gcc -pedantic -ansi -W -Wall funcptrcast.c -o funcptrcast
    funcptrcast.c: In function ‘main’:
    funcptrcast.c:5: attention : ISO C interdit la conversion d'un pointeur d'objet vers un type de pointeur à une fonction
    funcptrcast.c:6: attention : ISO C interdit la conversion d'un pointeur d'objet vers un type de pointeur à une fonction

    C'est d'ailleurs très discutable parce que ça aurait du sens sur les architectures purement Harvard, mais ça devrait être une exception gérée par le compilo concerné et pas une généralité de la norme C puisqu'il est établi qu'un pointeur, en général, peut très bien accéder une zone de mémoire contenant du code sur la plupart des architectures conventionnelles.

    Par contre, le contraire fonctionne bien !

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        *(void **)&(h._open)  = dlsym( RTLD_NEXT, "open");
        *(void **)&(h._close) = dlsym( RTLD_NEXT, "close" );

    C'est même sensiblement plus lisible parce que plus court, moins complexe et parce que le type est le même à chaque appel.

    ÉDIT : La norme C99 (enfin, n1256) spécifie explicitement cette possibilité :

    J.5.7 Function pointer casts
    1 A pointer to an object or to void may be cast to a pointer to a function, allowing data to
    be invoked as a function (6.5.4).
    2 A pointer to a function may be cast to a pointer to an object or to void, allowing a
    function to be inspected or modified (for example, by a debugger) (6.5.4).
    Mais GCC cesse de se plaindre également dès lors que l'on enlève « -pedantic », même avec « -std=c89 ». La man page de GCC spécifie :

    Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.

    […]

    Some users try to use -pedantic to check programs for strict ISO C conformance. They soon find that it does not do quite what they want: it finds some non-ISO practices, but not all---only those for which ISO C requires a diagnostic, and some others for which diagnostics have been added.
    Je ne sais pas dans quelle section de la norme ces contrôles stricts sont définis.

  6. #6
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juillet 2011
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 41
    Points : 40
    Points
    40
    Par défaut
    Ca marche !
    Enfin disparus ces warnings et le code fonctionne toujours !

    Merci à tous pour votre aide.

    Obsidian est un authentique guru, merci à lui de prendre le temps de faire part de son savoir à des développeurs de mon niveau.

    A l'occasion, il faudra que tu m'orientes sur un échange en MP ou un tuto balaise pour que je comprenne ces cast de fonctions qui me semblent encore bien mystérieux.

  7. #7
    Expert éminent
    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 : 38
    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
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par Obsidian
    Par contre, le contraire fonctionne bien !
    Mais c'est toujours pas portable . Soyons bien d'accord, je parle de portabilité absolue, c'est-à-dire vis-à-vis de la norme. Je ne remets pas du tout en cause le fait qu'il existe pas mal de plateformes pour lesquelles cette conversion a un sens.

    Citation Envoyé par Obsidian
    ÉDIT : La norme C99 (enfin, n1256) spécifie explicitement cette possibilité :
    Je précise juste pour éviter certaines mauvaises interprétations, que ce n'est pas la norme qui le spécifie, mais un document en annexe : J.5 Common extensions. Ces "extensions populaires" ne font pas partie de la norme.

    Citation Envoyé par Obsidian
    Je ne sais pas dans quelle section de la norme ces contrôles stricts sont définis.
    La stricte conformité signifie juste que le programme n'utilise aucune fonctionnalité non décrite par la norme. Comme la norme ne dit rien sur l'interchangeabilité entre pointeurs d'objet et pointeurs de fonction, un programme strictement conforme ne doit pas supposer qu'elle soit possible.

    Citation Envoyé par TomTom68
    Obsidian est un authentique guru
    Obsidian :

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    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 387
    Points : 23 702
    Points
    23 702
    Par défaut
    Citation Envoyé par Melem Voir le message
    Mais c'est toujours pas portable . Soyons bien d'accord, je parle de portabilité absolue, c'est-à-dire vis-à-vis de la norme. Je ne remets pas du tout en cause le fait qu'il existe pas mal de plateformes pour lesquelles cette conversion a un sens.

    Je précise juste pour éviter certaines mauvaises interprétations, que ce n'est pas la norme qui le spécifie, mais un document en annexe : J.5 Common extensions. Ces "extensions populaires" ne font pas partie de la norme.
    Oui, oui, on est bien d'accord. J'ai justement mis le smiley pour montrer que c'était une manière de « tricher » (et qu'à mon avis, c'est la plus propre). C'est d'ailleurs étonnant que GCC ne se plaigne pas dans ce sens-là puisque la norme ne définit pas plus la conversion pointeur de fonction vers pointeur d'objet que l'inverse.

    Mais comme tu l'as fait remarquer toi-même, le prototype de memcpy() est lui-aussi composé de types void * et le problème demeure.

    Citation Envoyé par TomTom68 Voir le message
    Obsidian est un authentique guru, merci à lui de prendre le temps de faire part de son savoir à des développeurs de mon niveau.
    Obsidian :
    Oulala ! :-) C'est très flatteur mais ce n'est malheureusement pas vrai. Melem et Diogène, par exemple, sont bien meilleurs que je ne le suis…

    A l'occasion, il faudra que tu m'orientes sur un échange en MP ou un tuto balaise pour que je comprenne ces cast de fonctions qui me semblent encore bien mystérieux.
    Il y avait ici un commentaire qui expliquait bien la chose mais que, malheureusement, je ne retrouve plus. Quoiqu'il en soit, ça devient plus clair si tu admets qu'il y a au moins deux cas où l'on définit le type d'un symbole en mettant des choses à sa droite : les tableaux et les fonctions.

    Décomposons le cas qui t'intéresse : « (int(*)(const char *,int,mode_t)) »

    • On commence par le symbole lui-même — quand il existe ! Dans le cas du prototype d'une fonction, on passe le type seul et le nom du paramètre est optionnel. Donc :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      (int(*ptr)(const char *,int,mode_t))
      ;
    • On le fait précéder d'une étoile pour indiquer qu'il s'agit d'un pointeur de fonction, et pas d'une définition classique :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      (int(*ptr)(const char *,int,mode_t))
      ;
    • On est obligé de les encadrer par une paire de parenthèses pour éviter une ambiguité. Sans elles, l'étoile s'appliquerait à gauche sur le type de la fonction et on définirait une fonction ordinaire renvoyant un pointeur sur quelque chose :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      int(*ptr)(const char *,int,mode_t))
      ;
    • On indique que cette expression représente une fonction de la même façon qu'en déclarant une fonction ordinaire : on la fait suivre d'une paire de parenthèses contenant les arguments. Note que j'ai fait disparaître le symbole « ptr » :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      (int(*)(const char *,int,mode_t))
      ;
    • Une fonction, comme une variable, ou n'importe quelle expression mathématique, peut être évaluée. Et puisqu'elle a une valeur, elle a un type. Du point de vue du programme, ce type sera celui de la valeur renvoyée à l'exécution par la fonction. Tu qualifies donc l'expression entière en la faisant précéder de son type, comme pour une variable :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      (int(*)(const char *,int,mode_t))
      ;
    • À ce stade, tu as une définition de type complète. Si tu voulais t'en servir pour déclarer une variable (donc un pointeur de fonction) — ou un nom de type avec typedef, chose importante — tu placerais le symbole au milieu de la définition, là où j'ai écrit ptr dans mes premières lignes ;
    • Mais tu peux surtout utiliser ce type anonyme tel quel soit en tant qu'argument de fonction (si tu veux passer ce pointeur à une fonction), soit dans le cadre d'un transtypage. Dans ce cas, comme avec les casts plus ordinaires, tu encadres le type complet avec des parenthèses :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      (int(*)(const char *,int,mode_t))
      ;


    Évidemment, il est beaucoup plus aisé de faire un typedef sur cette expression et d'utiliser ensuite le symbole ainsi défini de manière plus classique.

    Dernier petit détail : si tu veux t'exercer, essaie de deviner comment on écrirait une fonction qui retournerait un tel pointeur (sans typedef). :-)

  9. #9
    Expert éminent
    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 : 38
    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
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par Obsidian
    C'est d'ailleurs étonnant que GCC ne se plaigne pas dans ce sens-là puisque la norme ne définit pas plus la conversion pointeur de fonction vers pointeur d'objet que l'inverse.
    Moi aussi j'étais persuadé que le même warning existait aussi dans l'autre sens. Avec ce que tu viens de nous montrer, je pense finalement que le soucis de gcc n'était pas vraiment de l'ordre de la stricte conformité tel que le message veut nous le faire croire, mais plutôt de sûreté et de sécurité du programme. En effet, comme c'est l'OS qui dit quelles zones de la mémoire sont exécutables et lesquelles ne le sont pas, quelles zones peuvent être écrites et lesquelles ne le peuvent pas etc., gcc pense que la conversion d'un pointeur de fonction vers pointeur d'objet ou void est plus safe que l'inverse puisqu'elle consiste en quelque sorte à retirer un privilège (le privilège "exécutable") à la mémoire alors que dans le sens inverse en ajoute sans garanti que la mémoire la possède réellement. En gros c'est un peu comme le type * vers const type * qui est autorisé alors que l'inverse non.

    Citation Envoyé par Obsidian
    Oulala ! :-) C'est très flatteur mais ce n'est malheureusement pas vrai. Melem et Diogène, par exemple, sont bien meilleurs que je ne le suis…
    Encore pour ton humilité .

  10. #10
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    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 387
    Points : 23 702
    Points
    23 702
    Par défaut
    Citation Envoyé par Melem Voir le message
    […] Avec ce que tu viens de nous montrer, je pense finalement que le soucis de gcc n'était pas vraiment de l'ordre de la stricte conformité tel que le message veut nous le faire croire, mais plutôt de sûreté et de sécurité du programme. En effet, comme c'est l'OS qui dit quelles zones de la mémoire sont exécutables et lesquelles ne le sont pas, quelles zones peuvent être écrites et lesquelles ne le peuvent pas etc., gcc pense que la conversion d'un pointeur de fonction vers pointeur d'objet ou void est plus safe que l'inverse puisqu'elle consiste en quelque sorte à retirer un privilège (le privilège "exécutable") à la mémoire alors que dans le sens inverse en ajoute sans garanti que la mémoire la possède réellement. En gros c'est un peu comme le type * vers const type * qui est autorisé alors que l'inverse non.
    Je me suis posé la question aussi mais en fait, ça ne tient pas réellement non plus : dans l'absolu, un code peut être exécuté sans que le processus n'ait droit de lecture sur le code. C'est cohérent d'un point de vue commercial. :-)

    En fait, je pense que la séparation nette entre pointeurs de fonctions et pointeurs de données se justifie surtout pour les architectures Harvard. Si les bus d'adressage du code et des données sont distincts et dans des espaces différents, non seulement la conversion n'aura jamais de sens, mais elle ne sera pas forcément possible (formats différents). Si on considère les architectures de Von Neumann comme étant la généralité et les Harvard comme des exceptions, alors il faudrait que le compilo lève une erreur dans cette dernière architecture, ce qui rendrait le code normalisé non portable. Il est plus simple de dire que c'est interdit partout.

    Ça ne nous explique toujours pas pourquoi GCC est tolérant sur ce point, et il doit y avoir une raison (probablement écrite en commentaires dans le code de GCC) mais, à vue de nez, je vois deux hypothèses possibles :

    • Soit GCC a prévu un cas de failsafe qui marche toujours, justement pour éviter de se retrouver dans une impasse ;
    • Soit (hypthèse privilégiée), ça fonctionne parce que dans le premier cas, il fallait convertir la valeur retournée par dlsym(), ce qui n'est pas forcément possible alors que dans le second, je dépose directement la valeur telle quelle à l'endroit pointé sans me soucier de ce qui s'y trouve et, donc, sans avoir à effectuer de conversion.


    Mais par contre, la section 6.3.2.3 concernant les conversions de type précise quand même quelque chose d'intéressant :

    Citation Envoyé par n1256§6.3.2.3
    5 An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation. ⁵⁶⁾

    6 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

    […]

    56) The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment.
    Ceci est fait pour pouvoir représenter une adresse de façon numérique et donc la spécifier en dur dans les environnement où cela se justifie. Ex : « void * ptr = 0x12345678 ».

    Du coup, j'ai l'impression que la technique la plus sûre et la plus « C-compliant » serait une horreur du style :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     h._open  = (int(*)(const char *,int,mode_t)) (unsigned long int) dlsym( RTLD_NEXT, "open"  );
     h._close = (int(*)(int))                     (unsigned long int) dlsym( RTLD_NEXT, "close" );

    … soit un double-cast consistant à transformer le pointeur void en entier (donc en adresse numérique) et à retranstyper immédiatement cet entier vers un nouveau pointeur. C'est légal sur toute la ligne et mes tests fonctionnent bien. Ça a en plus l'avantage de nous laisser spécifier les vrais types terminaux au lieu de mentir en disant « void ** ».

  11. #11
    Expert éminent
    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 : 38
    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
    Points : 8 389
    Points
    8 389
    Par défaut
    En fait, je pense que la séparation nette entre pointeurs de fonctions et pointeurs de données se justifie surtout pour les architectures Harvard.
    Ca c'est pour la norme, la généralité. Mais pour notre gcc qui compile ici sous un linux sur une architecture von neumann et qui n'a pas apprécié la conversion, je pense qu'on peut maintenir mon hypothèse.

    Du coup, j'ai l'impression que la technique la plus sûre et la plus « C-compliant » serait une horreur du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    h._open  = (int(*)(const char *,int,mode_t)) (unsigned long int) dlsym( RTLD_NEXT, "open"  );
    h._close = (int(*)(int)) (unsigned long int) dlsym( RTLD_NEXT, "close" );
    intptr_t à la place de unsigned long serait encore mieux. Sinon c'est en effet, à mon avis, la meilleure façon de contourner les messages de warning causés par les casts pointeur d'objet <-> pointeur de fonction quand on veut les ignorer.

  12. #12
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    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 387
    Points : 23 702
    Points
    23 702
    Par défaut
    Ca c'est pour la norme, la généralité. Mais pour notre gcc qui compile ici sous un linux sur une architecture von neumann et qui n'a pas apprécié la conversion, je pense qu'on peut maintenir mon hypothèse.
    C'est ce que je dis aussi : la norme choisit volontairement de ne pas définir les transtypages entre pointeurs de données et pointeurs de fonction, probablement pour les raisons que je propose. Le fait que, du coup, cela reste tout-à-fait possible (et justifié) sur une Von Neumann reste quand même un cas particulier, non universel. Et un code normalisé deviendrait non-portable.

    intptr_t à la place de unsigned long serait encore mieux. Sinon c'est en effet, à mon avis, la meilleure façon de contourner les messages de warning causés par les casts pointeur d'objet <-> pointeur de fonction quand on veut les ignorer.
    Voila ! C'est le type que je recherchais. Je te remercie.

  13. #13
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juillet 2011
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 41
    Points : 40
    Points
    40
    Par défaut
    Bonjour,

    #include <stdint.h>
    These allow you to declare variables of the same size as a pointer.
    typedef int16_t intptr_t
    Donc si j'ai bien suivi, il vaut mieux écrire ainsi la mémorisation du pointeur de fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    h._open  = (int(*)(const char *,int,mode_t)) (intptr_t) dlsym( RTLD_NEXT, "open" );
    h._close = (int(*)(int)) (intptr_t) dlsym( RTLD_NEXT, "close" );
    Merci de confirmer.

  14. #14
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    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 387
    Points : 23 702
    Points
    23 702
    Par défaut
    C'est bien ça, mais c'est mieux si tu laisses un commentaire sans ambiguïté avant ces lignes expliquant le pourquoi de la chose. Sinon, les gens qui passeront après toi risquent de te prendre pour un programmeur très sale. :-)

  15. #15
    Membre émérite Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Points : 2 280
    Points
    2 280
    Par défaut
    Bonjour, pour apporter ma modeste contribution à l'édifice, je voulais simplement rappeler que ce comportement est bien défini par la norme POSIX 2008:
    2.12.3 Pointer Types

    All function pointer types shall have the same representation as the type pointer to void. Conversion of a function pointer to void * shall not alter the representation. A void * value resulting from such a conversion can be converted back to the original function pointer type, using an explicit cast, without loss of information.

    Note:
    The ISO C standard does not require this, but it is required for POSIX conformance.
    Cordialement.

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

Discussions similaires

  1. ISO C++ forbids declaration of SHA1
    Par ikuzar dans le forum Débuter
    Réponses: 6
    Dernier message: 21/02/2011, 11h42
  2. comparison between pointer and integer
    Par sculpteur dans le forum Objective-C
    Réponses: 1
    Dernier message: 03/12/2010, 17h31
  3. Réponses: 3
    Dernier message: 20/08/2009, 20h46
  4. ISO C++ forbids declaration
    Par inddzen dans le forum C++
    Réponses: 17
    Dernier message: 20/01/2008, 18h23
  5. Réponses: 9
    Dernier message: 15/02/2005, 13h26

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