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 :

comportement non attendu avec memcpy


Sujet :

C

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Points : 114
    Points
    114
    Par défaut comportement non attendu avec memcpy
    Bonjour,

    J aimerai copier une variable dans une chaine de caractere.

    Par exemple copier l entier int i = 123 dans la chaine de caractere char *s.
    Lorsque je dis copier, j aimerai que les 4 octets de i soient recopier dans les 4 premier octets de s.

    Voici mon code :

    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
     
          1 #include <stdio.h>
          2 #include <stdlib.h>
          3 #include <string.h>
          4
          5
          6
          7 int main(void)
          8 {
          9     char *s = calloc(5, sizeof(char)); // j alloue la taille d'un int + 1 pour le caractere de fin de chaine.
         10     const int i = 134423;
         11
         12     memcpy(s, &i, 4);
         13     printf("%d\n", *s);   // j affiche les 4 premier octets.
         14
         15     return 0;
         16 }
    Cela affiche :

    Ou ai je puis faire une erreur ???

    Merci

  2. #2
    Membre habitué Avatar de _kal_
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2006
    Messages
    178
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Janvier 2006
    Messages : 178
    Points : 156
    Points
    156
    Par défaut
    Que souhaite tu réaliser?

    Si tu veux convertir un int en char *, il existe d'autres solutions plus propres.

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Oh my god...

    1) pour ecrire un entier dans une chaine, c'est
    sprintf (zone, "%d", entier)
    2) pas besoin d'allocation dynamique, un tableau de caractere de taille fixe suffit
    3) il manque le free

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Au fait, arretez de croire que "char *" = "chaine de caractere"
    On est pas en VB, ni PHP
    Il faut raisonner par "zones memoire"

  5. #5
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *s = calloc(5, sizeof(char));
    plutôt:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *s = calloc(sizeof(int)+1, sizeof(char));
    et:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    memcpy(s, &i, sizeof(int));
    pour la portabilité.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  6. #6
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    1) pour ecrire un entier dans une chaine, c'est
    sprintf (zone, "%d", entier)
    Pas ici:
    Lorsque je dis copier, j aimerai que les 4 octets de i soient recopier dans les 4 premier octets de s.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  7. #7
    Membre actif Avatar de Pikwik
    Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2006
    Messages : 237
    Points : 252
    Points
    252
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    printf("%d\n", *s);   // j affiche les 4 premier octets.
    Pourquoi "*s" ?

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Bon et pour repondre au probleme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%d\n", *((int *)s));
    sauf que c'est debile de passer par un char *, si tu veux l'utiliser comme un int *

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Citation Envoyé par seriousme
    Lorsque je dis copier, j aimerai que les 4 octets de i soient recopier dans les 4 premier octets de s.
    Oué, ok, désolé
    Mais, je vois pas trop l'utilité
    A la limite dans une zone de type unsigned char, dans le but de serialiser la donnée, pour envoyer sur le reseau ou dans un fichier
    Mais ça peut se faire directement par fwrite

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Points : 114
    Points
    114
    Par défaut
    Citation Envoyé par Gruik
    1) pour ecrire un entier dans une chaine, c'est
    sprintf (zone, "%d", entier)
    Ce n est pas ce que je veux faire.
    J ai envoie de copier les 4 bytes de l entier dans les 4 byte de s.
    Or avec sprintf la taille de s est pas egale a 4 mais egale au nombre de chiffre qu a l entier i.

    par exemple i = 255

    alors i (en bas 2) = 00000000 00000000 0000000 11111111

    j ai envie que
    s[0] (en base 2) = 00000000
    s[1] (en base 2) = 00000000
    s[2] (en base 2) = 00000000
    s[3] (en base 2) = 11111111

    Citation Envoyé par Gruik
    2) pas besoin d'allocation dynamique, un tableau de caractere de taille fixe suffit
    Certes, mais ce ce que je fais n est pas faux non plus.

    Citation Envoyé par Gruik
    3) il manque le free
    Alors la je n ai rien a redire .

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Points : 114
    Points
    114
    Par défaut
    tout a fait ca je doit envoyer sur un reseau plusieurs information.
    Ce que je voulais faire c etait de creer une chaine de caracteres, comme ca je met les informations voulues, .... et j envoie

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Dans ce cas la...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int a = 0x7f00ff80;
    char * s = (char *)&a;
    A priori, ça devrait donner
    s[0] (en base 2) = 01111111
    s[1] (en base 2) = 00000000
    s[2] (en base 2) = 11111111
    s[3] (en base 2) = 10000000

    ..mais ya des histoires de big endian / little endian, y se peut que l'ordre soit l'inverse..

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727
    Par défaut
    Citation Envoyé par berg
    tout a fait ca je doit envoyer sur un reseau plusieurs information.
    Ce que je voulais faire c etait de creer une chaine de caracteres, comme ca je met les informations voulues, .... et j envoie
    Dans ce cas, il faut vraiment faire attention à l'ordre des octets quand on envoie et reconstitue l'entier...
    Yavait un fonction dans la librairie reseau pour convertir big endian en little endian et vice versa.

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

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Points : 1 727
    Points
    1 727

  15. #15
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Points : 114
    Points
    114
    Par défaut
    ok merci pour voter aide !!!


  16. #16
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Si tu veux que ça marche correctement, il faut faire comme ça :
    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 <stdlib.h>
    #include <string.h>
    int main(void)
    {
    	char *s = calloc(1, sizeof(int)); // j alloue la taille d'un int 
         const int i = 134423;
     
         memcpy(s, &i, sizeof(int));
         printf("%d\n", *(int *)s);   // j affiche l'entier
         free(s);
     
         return 0;
    }
    Le %d suppose que l'argument passé est un entier, donc il faut lui passer un entier. s est un pointeur vers une chaîne de caractères à l'origine, tu as "détourné" ce "pointeur de caractères" en pointeur vers un entier, donc il faut explicitement écrire le processus de transformation dans le printf.
    "La haine seule fait des choix" - Koan Zen
    "Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
    "Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
    Faites du Prolog, ça vous changera les idées !
    Ma page Prolog
    Mes codes sources commentés

    Mon avatar : La Madeleine à la veilleuse de Georges de La Tour

Discussions similaires

  1. Div avec des dimensions non attendues
    Par Amerzone38 dans le forum Mise en page CSS
    Réponses: 5
    Dernier message: 22/03/2010, 10h54
  2. [JButton] Background non coloré avec LnF Windows
    Par leminipouce dans le forum Composants
    Réponses: 7
    Dernier message: 03/10/2005, 13h48
  3. Réponses: 5
    Dernier message: 02/09/2005, 12h47
  4. Réponses: 5
    Dernier message: 12/05/2005, 10h49
  5. Réponses: 4
    Dernier message: 07/12/2002, 15h24

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