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 :

Conversion void* et double


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 42
    Par défaut Conversion void* et double
    Bonjour,

    pourquoi en C on ne peut pas convertir un void* en double je croyais que le type void etait le type générique ?

    merci d'avance.

  2. #2
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Salut,

    void * est le type de pointeur générique, pas le type générique. Tu peux caster un "void *" en "double *" mais pas en "double".
    Le type void tout court n'a pas de sens, à part dans les signatures de fonction.

  3. #3
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    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 393
    Par défaut
    void* est un pointeur générique, mais reste un pointeur.
    double, c'est un nombre.

    Edit: Non seulement je me fais griller, mais en plus je dis des conneries...
    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.

  4. #4
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Médinoc
    void* est un pointeur générique, mais reste un pointeur.
    double, c'est un entier.
    Tu a voulu dire nombre à virgule flottante...

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 42
    Par défaut
    ah ok merci et pourquoi ca ca marche :

    tabgen[i]= (long *)(atol(tabE[i]));

    et pas ca :

    tabgen[i]= (double *)(atof(tabE[i]));

    avec tabgen[i] de type void **

  6. #6
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Si on veut se la jouer chacal, on peut se permettre de caster un int/long en void *, car il s'avere qu'un pointeur (de n'importe quel type) prend la meme place qu'un entier long sur pas mal de plateformes.
    Mais faire ça c'est casser l'abstraction du sizeof

    double prend plus de place qu'un int et donc ça ne rentre pas dans un void *

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 42
    Par défaut
    merci,

    encore un question alors pourquoi le type float qui est sur 4octets interdis aussi cela ?

  8. #8
    Membre expérimenté Avatar de Bob.Killer
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    336
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 336
    Par défaut
    Il faut utiliser les bonnes fonctions

    atol() Convert string to long (function)
    atoi() Convert string to integer (function)
    atof() Convert string to double (function)

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 42
    Par défaut
    non non j'ai juste fais unmauvais copier coller je corrige le probleme n'est pas la

  10. #10
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Bob.Killer
    Il faut utiliser les bonnes fonctions

    atol() Convert string to long (function)
    atoi() Convert string to integer (function)
    atof() Convert string to double (function)
    Obsolète! On utilise aujourd'hui strtol(), strtol() et strtod() respectivement qui permettent une meilleure gestion des erreurs que ato*().

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 42
    Par défaut
    Une idée sur le fait que on puisse convertir void * en int/long (meme si c'est pas propre) à cause de la representation en memoire de 4octets et pas en float qui est aussi sur 4octets ?

  12. #12
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Ca y'est j'ai compris, on s'est emmelé les pinceaux.

    tabgen[i]= (long *)(atol(tabE[i]));

    et pas ca :

    tabgen[i]= (double *)(atof(tabE[i]));
    Ici, le probleme n'est pas dans l'affectation du "long *" ou "double *" dans tabgen[i], le probleme est le castage du atol() et du atof() en pointeur.
    atof() retourne tout le temps un double, donc tu pourras jamais caster le retour de atof en pointeur.
    Si atof retournait un float alors ça serait peut être possible
    Yaurait qu'a tester ceci
    (double *)((float)atof(tabE[i]));

  13. #13
    Membre émérite Avatar de crocodilex
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    697
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 697
    Par défaut
    Citation Envoyé par Gruik
    Yaurait qu'a tester ceci
    (double *)((float)atof(tabE[i]));
    Je ne vois pas trop l'interêt. Je trouve cette écriture complètement absurde...

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 42
    Par défaut
    Oui mais mon compilo m'empeche de convertir un float ou un double vers leur pointeur respectif et donc encore moi un float vers un pointeur sur double c'est illégal

    d'ailleurs c'est bizarre de pas pouvoir caster un float en float* alors qu'un long en long* on peut

  15. #15
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Citation Envoyé par crocodilex
    Je ne vois pas trop l'interêt. Je trouve cette écriture complètement absurde...
    Hé ho, j'ai pas dit qu'il fallait faire ça, c'était pour tester ce qu'autorisait le compilateur

  16. #16
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Citation Envoyé par EnigmuS
    Oui mais mon compilo m'empeche de convertir un float ou un double vers leur pointeur respectif et donc encore moi un float vers un pointeur sur double c'est illégal

    d'ailleurs c'est bizarre de pas pouvoir caster un float en float* alors qu'un long en long* on peut
    Ok, j'ai dit des conneries alors (sur le coup du double trop grand pour rentrer dans un pointeur)

  17. #17
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    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 393
    Par défaut
    Il faut dire que dans tous les cas, ce genre de transtypage est un hack affreux.
    Les seuls types de nombres qu'on devrait pouvoir convertir en pointeurs, sont intptr_t et consorts...
    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.

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 42
    Par défaut
    bein si tu sais comment on déreference un pointeur (on obtient la valeur pointée) en assembleur ca m'intéresse car si je convertis comme ca pour les mettre dans le tableau génériquec'est pour générer la signature d'un appel à une DLL qui prend n'importe quoi comme type (pointeur ou pas) et qui est appelé via de l'assembleur alors quand j'ai des pointeurs sur double ca va mais quand j'ai des doubles ca aime moins

    enfin je découvre et je galére y a surement d'autre solution et je vois bien que c'est moche

  19. #19
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Bah le type du pointeur peut être modifié (on peut tres bien mettre un "double *" dans un "void *") ce qu'il faut pas faire c'est mettre un "scalaire" (entier, flottant, structure) dans un pointeur. Si ça doit arriver : donner l'adresse de ce scalaire -- à condition qu'il soit disponible tant qu'on maintient une pointeur sur lui -- la solution la plus sure est alors de "mallocopier" ce scallaire et de libérer cette copie quand on en a plus besoin

    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
     
    void * ptr_gen;
    double mon_scalaire;
    double * tmp_ptr;
     
    mon_scalaire = 42.42;
    tmp_ptr = malloc(sizeof mon_scalaire);
    memcpy(tmp_ptr, &mon_scalaire, sizeof mon_scalaire);
    ptr_gen = tmp_ptr;
     
    /* -- plus loin : utilisation */
    tmp_ptr = ptr_gen; /* à condition de savoir que c'est en fait un pointeur sur double */
    mon_scalaire = *tmp_ptr;
     
     
    /* -- plus loin : liberation */
    free(ptr_gen);
    Une idee courante est de creer une structure contenant
    1) le pointeur vers la zone où ya la copie de la valeur
    2) un union avec tous les types dont on a besoin
    3) un enum indiquant le type

    Edit: avec cette structure il n'y a plus besoin de mallocopier un scalaire, une copie simple suffit

  20. #20
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par EnigmuS
    Une idée sur le fait que on puisse convertir void * en int/long (meme si c'est pas propre) à cause de la representation en memoire de 4octets et pas en float qui est aussi sur 4octets ?
    Parce qu'une adresse (la valeur d'un pointeur) est un valeur entière. Cela peut donc faire un certain sens de convertir la valeur d'un pointeur en un entier inversément. Par contre, je ne vois aucune raison d'autoriser un cast d'un pointeur en double.

    D'ailleurs, la portabilité du cast pointeur <-> entier n'est pas garantie. Selon la norme, le résultat de la conversion d'un entier en un type pointeur est définit par l'implantation. Ce résultat peut en effet ne pas être aligné correctement, et peut ne pas pointer sur un objet du type référencé. La conversion inverse est également définie par l'implantation, et le comportement est indéfini si la valeur du pointeur ne peut être représentée dans le type entier hôte.

    A priori, il n'est pas garantit qu'un int ou long puisse recevoir la valeur d'un pointeur. Pour les raisons énoncées ici, la norme C99 a introduit les types intptr_t et uintptr_t, déclarés dans stdint.h, qui ont la propriété suivante:

    "N'importe quel pointeur générique valide peut être converti dans ce type, puis re-converti en pointeur sur void, et le résultat de cette double conversion sera comparé égal avec la valeur du pointeur original".

    Si vraiment tu tiens à convertir ton pointeur en double, et que ton compilateur est comforme à C99, rien ne t'empêche de procéder en deux temps comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <stdio.h>
    #include <stdint.h>
     
    int main(void)
    {
        int nombre = 10;
        int *pNombre = &nombre;
     
        uintptr_t pvaleur = (uintptr_t) (void *) pNombre;
        double pvaleur_dbl = pvaleur;
     
     
        return 0;
    }
    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

Discussions similaires

  1. [Conversion]int to double
    Par frouge dans le forum Général Java
    Réponses: 6
    Dernier message: 03/02/2012, 09h34
  2. Conversion de type double en texte
    Par CoachMac dans le forum C
    Réponses: 17
    Dernier message: 14/10/2006, 19h29
  3. [VB.NET]Comment obtenir conversion exacte Single>Double?
    Par Misterburma dans le forum VB.NET
    Réponses: 9
    Dernier message: 09/02/2006, 22h24
  4. Problème conversion float vers double
    Par jhenaff dans le forum SQL Procédural
    Réponses: 3
    Dernier message: 27/01/2006, 10h39
  5. conversion string en double
    Par zmatz dans le forum SL & STL
    Réponses: 2
    Dernier message: 14/10/2005, 22h46

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