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 pour caster une variable


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 171
    Points : 55
    Points
    55
    Par défaut Problème pour caster une variable
    Bonjour, j'ai probleme pour caster une variable.
    J'ai le prototype de fonction suivant:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    void UART_puts(uart_id_e uart_id, uint8_t * str, uint8_t len)

    Lorsque j'initialise comme cela:
    Et que je cast la variable comme cela:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    UART_puts(UART3_ID, (uint8_t*)str, sizeof(str));	//Send the message to UART3 (Sigfox module)
    Je n'ai pas de probleme, cela fonctionne.

    Cependant, quand j'initialise comme cela:
    Je ne sais pas comment utiliser ma variable dans la fonction UART_puts.
    Quand j'ecris cela:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    UART_puts(UART2_ID, (uint8_t)c, sizeof(c));	//send frame to uart 2 (USB)
    J'obtiens cette erreur:
    ../Src/main.c:306:25: warning: passing argument 2 of 'UART_puts' makes pointer from integer without a cast [-Wint-conversion]
    UART_puts(UART2_ID, (uint8_t)c, sizeof(c)); //send frame to uart 2 (USB)
    Quand j'ecris cela:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    UART_puts(UART2_ID, (uint8_t*)c, sizeof(c));	//send frame to uart 2 (USB)
    J'obtiens cette erreur:
    ../Src/main.c:306:25: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    UART_puts(UART2_ID, (uint8_t*)c, sizeof(c)); //send frame to uart 2 (USB)
    ^
    Et quand j'ecris cela:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    UART_puts(UART2_ID, c, sizeof(c));	//send frame to uart 2 (USB)
    J'obtiens cette erreur:
    ../Src/main.c:306:25: warning: passing argument 2 of 'UART_puts' makes pointer from integer without a cast [-Wint-conversion]
    UART_puts(UART2_ID, c, sizeof(c)); //send frame to uart 2 (USB)
    ^
    Comment faire pour cette variable c soit "compatible" avec le prototype de fonction? Merci.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Il te faut un pointeur, donc operateur & UART_puts(UART2_ID, &c, 1);
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 171
    Points : 55
    Points
    55
    Par défaut
    Ok merci!

    Quelle est la difference entre
    *c
    et
    &c
    ?

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Quelle différence ? Il va sérieusement falloir réouvrir un cours de C à la rubrique "pointeurs" !

    Un code simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main() {
        int i = 42; // une variable
        int* p = &i; // un pointeur initialisé avec l'adresse de cette variable
        *p = 17; // modification de la variable pointée
        return i; // renvoie 17
    }
    &c a un sens quelque soit le type de la variable c : c'est son adresse ; *c n'a un sens que si le type de la variable c est "pointeur sur TOTO" : c'est la variable pointée, de type "TOTO".

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 171
    Points : 55
    Points
    55
    Par défaut
    Merci!

  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    J'oubliais juste de dire quelque chose de plus profond : caster, c'est mal.

    Quand tu castes, tu dis au compilateur : considère une variable comme étant d'un autre type, ne fait pas de vérification dessus. Des fois, ton cast fait trop n'importe quoi alors le compilateur râle quand même, mais en général, tu risques de masquer des problèmes. Si ton code est correct, tu as normalement jamais besoin de caster. Si tu as besoin de le faire, il faut faire très attention et avec de bonnes raisons. Juste "faire taire un warning du compilateur" n'est pas une bonne raison.

    Un exemple tout simple pour mieux me faire comprendre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>
     
    void print(float* p) {
        printf("%f", *p);
    }
     
    int main() {
        int i = 31415;
        print(&i);
    }
    Ce code génère un warning :
    main.c: In function 'main':
    main.c:9:11: warning: passing argument 1 of 'print' from incompatible pointer type [-Wincompatible-pointer-types]
         print(&i);
               ^
    main.c:3:6: note: expected 'float *' but argument is of type 'int *'
     void print(float* p) {
          ^~~~~
    Avec un cast, plus de warning ! Youpi !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>
     
    void print(float* p) {
        printf("%f", *p);
    }
     
    int main() {
        int i = 31415;
        print((float*) &i);
    }
    Sauf qu'à l’exécution ça ne fonctionne pas...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    0.000000
    Process finished with exit code 0
    PS : en C++, ce n'est pas un warning, c'est carrément une erreur !
    main.cpp:9:13: error: cannot convert 'int*' to 'float*' for argument '1' to 'void print(float*)'
         print(&i);
    Avec un cast, plus d'erreur... Youpi...

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Bktero Voir le message
    Sauf qu'à l’exécution ça ne fonctionne pas...
    Quand j'ai vu ça, je me suis dit "ok, je m'en vais te me le faire fonctionner ce cast !!!".
    Ben non. J'ai tout essayé (à partir de "i" casté en float) mais non, rien à faire.

    Ci-joint un de mes essais (ne compile pas)
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>
     
    void print(float* p) {
        printf("%f\n", *p);
    }
     
    int main() {
        int i = 31415;
        print((float*)(&((float)i)));
    }
    En fait, le souci, c'est que "i" casté en float n'est pas mis en mémoire et n'a donc pas d'adresse exploitable.

    Bravo Bel exemple de cast foireux et irréparable

    Citation Envoyé par Bktero Voir le message
    Youpi...
    Ouais pareil ouais
    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]

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Le l'adresse semble correcte, mais l'affichage est toujours de 0..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void print(float* p) {
        printf("%p:%f\n", p, *p);
    }
     
    int main() {
        int i = 31415;
        print((float*)((((void*)&i))));
        printf("%p", &i);
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    0x7ffc0cd40a2c:0.000000                                                                                                                                                            
    0x7ffc0cd40a2c
    Mais dans le debugger, la valeur de *p dans printf apparait comme 4.40217913e-41, et effectivement si on l'affiche avec la notation scientifique (%e), elle apparait.

    Peut-etre l'endianess et la representation en memoire du float qui entrent en jeu.
    Ca me rapelle https://bousk.developpez.com/traduct...alisation/#LIV
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Le l'adresse semble correcte, mais l'affichage est toujours de 0.
    ...
    Peut-etre l'endianess et la representation en memoire du float qui entrent en jeu.
    Exactement. L'adresse de i ça restera l'adresse de i quoi qu'il arrive. C'est la façon de décoder son contenu qui fait toute la différence.
    "i" est un int (4 octets) qui vaut 31415. Ce nombre "31415" est alors codé à la façon d'un int (une bête conversion de "31415" en binaire qui s'étale sur les 32 bits de cette variable).
    Ensuite, dans la fonction print il est écrit "on reçoit l'adresse d"un float". Quand ensuite la fonction utilise cette adresse (qui est alors la même, tout le monde en convient) et tente de convertir ce qui s'y trouve, ben elle utilise pour ça le codage des floats (mantisse, exposant, etc). Et là, le résultat n'est plus du tout la même chose alors que le contenu des 32 bits est le même. Simplement il n'est pas lu de la même façon.

    Dans "le crime de l'Orient Express" (Agatha Christie), à un moment Hercule Poirot tombe sur un mouchoir avec une lettre "H" brodée. Il cherche alors partout à qui appartient ce mouchoir (et bien évidemment on a un personnage dénommé "Hubbard" et un autre dénommé "Hildegarde" sinon mettre ce mouchoir dans l'intrigue n'aurait servi à rien).
    Et à la fin, il révèle qu'en caractère russe, le "H" se lit "N" et que le mouchoir appartient à Natalia Dragomirov. On a ici le même principe. Dans un alphabet un "H" se lit "H" et dans un autre il se lit "N". Et dans un codage X une suite de bits se lira "31415" et dans un autre, la même suite se lira "4.40217913e-41".

    La seule façon d'avoir "31415" à l'écran au sortir de l'affichage d'un float, c'est de réorganiser les bits qui composent ce nombre au format "float" avant de les envoyer à la fonction. Et la seule façon de faire ça est de recopier "i" dans une autre variable float => float f=(float)i (j'ai écrit le cast pour montrer qu'il existe mais si on ne le met pas il est alors implicite)

    PS: Dans "Indiana Jones et la dernière croisade" (ouais, j'ai des références ) il est dit qu'en latin, un "J" s'écrit "I"...
    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]

  10. #10
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bravo Bel exemple de cast foireux et irréparable
    Merci

    Citation Envoyé par Bousk Voir le message
    Le l'adresse semble correcte
    [...]
    Peut-etre l'endianess et la representation en memoire du float qui entrent en jeu.
    Citation Envoyé par Sve@r Voir le message
    Exactement. L'adresse de i ça restera l'adresse de i quoi qu'il arrive. C'est la façon de décoder son contenu qui fait toute la différence.
    En effet, tout est question de représentation ici. Le problème vient du fait qu'ici on caste un pointeur. On peut faire tous les casts qu'on veut, l'adresse reste la même et quand on regarde ce qu'il y a à cette adresse, on y trouve un entier 32 bits (sans doute représenté en complément à 2) et on interprète ces bits comme un flottant 32 bits en IEE754. Très peu probable que ça donne la même valeur dans les 2 représentations...

    Si la fonction print() prenait un flottant un paramètre (au lieu d'un pointeur sur flottant), l'affichage pourrait être correct. En effet, il existe des conversions légales entre types. Voici un tel code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>
     
    void print(float p) {
    	printf("%f", p);
    }
     
    int main() {
    	int i = 31415;
    	print(i);
    }
    Compilé avec -Wall -Wextra, il n'y a pas de warning.

    En ajoutant -Wconversion, le compilateur nous avertit d'une possible perte :
    main.c:9:8: warning: conversion to 'float' from 'int' may alter its value [-Wconversion]
      print(i);
            ^
    -Wconversion
    Warn for implicit conversions that may alter a value. This includes conversions between real and integer, like abs (x) when x is double; conversions between signed and unsigned, like unsigned ui = -1; and conversions to smaller types, like sqrtf (M_PI). Do not warn for explicit casts like abs ((int) x) and ui = (unsigned) -1, or if the value is not changed by the conversion like in abs (2.0). Warnings about conversions between signed and unsigned integers can be disabled by using -Wno-sign-conversion.

    For C++, also warn for confusing overload resolution for user-defined conversions; and conversions that never use a type conversion operator: conversions to void, the same type, a base class or a reference to them. Warnings about conversions between signed and unsigned integers are disabled by default in C++ unless -Wsign-conversion is explicitly enabled.
    Bien sûr, un cast empêche le warning d'apparaitre. Dans les 2 cas, la sortie console est bien 31415.000000. En revanche, si i = 987654321, alors la sortie devient 987654336.000000... Et de manière marrante, si i =987654336 alors la sortie est toujours 987654336.000000 est correcte

    PS : amusez-vous à rajouter -Wconversion à vos projets, vous allez sans doute vous marrer

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

Discussions similaires

  1. Problème pour modifier une variable globale
    Par supertom dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 6
    Dernier message: 07/06/2007, 18h00
  2. Réponses: 17
    Dernier message: 01/06/2007, 08h16
  3. Problème pour inclure une variable à un objet
    Par yoyo29 dans le forum Tkinter
    Réponses: 2
    Dernier message: 04/05/2007, 13h01
  4. Réponses: 2
    Dernier message: 14/04/2006, 18h40
  5. Probléme pour insérer une variable dans un champs
    Par BOUTRAIS dans le forum Access
    Réponses: 2
    Dernier message: 11/04/2006, 22h45

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