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 :

information sur memcpy


Sujet :

C

  1. #1
    Membre actif Avatar de fahdijbeli
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2012
    Messages : 281
    Points : 240
    Points
    240
    Par défaut information sur memcpy
    bonjour ,
    je fait une fonction qui possède un paramètre (générique) de type :
    je veux dire par générique car ce paramètre elle prend n'importe quel type comme le void * mais de moi je préfere le char * car pour le char je vais manipuler les octets , je montre le code pour comprendre :
    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    typedef struct
    {
      unsigned int IP_MULTICAST;
      unsigned int IP_LOCAL;
    }IP_MREQTypeDef;
     
     
     
    void test(const char * buff, int length)
    {
        char s[100];
     
        memcpy(s,buff,length);
        printf("%s",s);
        printf("%d",strlen(s));
    }
     
     
    int main()
    { int i,j;
        IP_MREQTypeDef x;
        x.IP_MULTICAST=49;
        x.IP_LOCAL=50;
        test((char*)&x,sizeof(IP_MREQTypeDef));
           return 1;
    }
    voyez ici la fonction test elle possède un paramètre c'est le paramètre générique . lors de l'appelle de cette fonction j'ai passé à ce paramètre une structure avec la cast bien sure . maintenant dans la fonction test je veux copier les 2 attributs de cette structure dans une chaîne de caractère juste je parle des octets donc copier les 4 octets de première attribut vers les 4 premiers octets de s et puis la deuxième , le problème ici lorsque j'exécute ce programme il m'affiche que 1 car le code ascii 49 avec un taille de s est 1 il a pas récupéré la deuxième valeur , je sais le problème c'est quoi car ici le première attribut sur 4 octet avec la valeur de 49 occupe un seul octet donc le reste des octets sont à NUL dans ce cas la je pense que la fonction memcpy lorsque elle trouve un NUL elle sarrette et l'autre attribut ne sera copié. j'ai posté ici pour me trouvé une solution pour ça ou bien une autre méthode . bon j'ai dit ce paramètre générique car je peux par exemple passer un int non un struct
    et merci pour l'aide .

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    Tu passes à printf une chaîne de caractère donc celui-ci s'arrête au premier '\0' rencontré.

    Je n'ai pas testé, mais pour ce que tu veux faire, je pense que cette solution serait plus adaptée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void mon_print(const char * s, size_t taille)
    {
           char format[1<<( sizeof(size_t) - 1) + 3]; // taille maximale
           sprintf(format, "%d%%c", taille);
           printf( format, s);
    }

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Salut
    C'est un peu un gros fatras ton discours. Bon, sinon la réponse est facile
    1) la fonction memcpy() ne s'arrête pas à un caractère précis ; ce n'est pas une copie de chaine. C'est d'ailleurs pour ça qu'on lui passe la taille de la zone. Donc je peux t'assurer que ta copie se fait intégralement
    2) tu affiches ta zone avec un format "%s" comme si c'était une chaine de caractères (sous-entendu elle possède impérativement un '\0'). Or rien n'oblige cette zone a en avoir un. Toutefois, que se passe-t-il si elle en contient par hasard un par exemple en seconde position ? Je te laisse répondre tout seul à cette question (et c'est pareil avec strlen())
    3) ton analyse de la structure est correct en théorie. Dans la réalité, il peut arriver que le compilo rajoute des octets "de bourrage". Et donc peut-être que IP_MULTICAST commence en position 2 et IP_LOCAL en position 7 (j'exagère bien sûr mais c'est pour illustrer)
    4) que se passe-t-il si la zone à copier fait plus de 100 char ?

    Accessoirement utiliser un char* au lieu d'un void* peut se justifier (après-tout, c'était comme ça avant) mais ça oblige l'appelant à faire un cast. Alors que si tu te forçais un peu à faire toi le cast depuis un void* cette fonction serait plus souple pour les autres ce qui est bien appréciable.

    Ta fonction rectifiée
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void test(const char * buff, int length)
    {
        char s[100];
     
        memcpy(s,buff,length);
        write(1, s, length);
        printf("%d",length);
    }
    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]

  4. #4
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    memcpy(s,buff,length);
    write(1, s, length);
    Pour des raisons de performances et de portabilité, ne devrait-on pas utiliser fwrite (ainsi C) à la place de write ?

    Sinon, 1 correspond à la sortie standard, mais il n'y a pas un define existant pour éviter d'écrire un nombre magique (nombre écrit en dur dans le programme) ?

  5. #5
    Membre expérimenté Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    625
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 625
    Points : 1 564
    Points
    1 564
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Salut
    Ta fonction rectifiée
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void test(const char * buff, int length)
    {
        char s[100];
     
        memcpy(s,buff,length);
        write(1, s, length);
        printf("%d",length);
    }
    Si la fonction est rectifiée comme tu le dis, on peut encore la simplifier
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void test(const char * buff, int length)
    {
        write(1, buff, length);
        printf("%d",length);
    }
    Je n'ai pas vraiment regardé le reste....
    On écrit "J'ai tort" ; "tord" est la conjugaison du verbre "tordre" à la 3ème personne de l'indicatif présent

  6. #6
    Membre actif Avatar de fahdijbeli
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2012
    Messages : 281
    Points : 240
    Points
    240
    Par défaut
    merci les amis

  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 690
    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 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Pour des raisons de performances et de portabilité, ne devrait-on pas utiliser fwrite (ainsi C) à la place de write ?
    Pas savoir. Perso je préfère les fonctions bas niveau (c'est toi qui gère le buffer) plutôt que les fonctions bufferisées.

    Citation Envoyé par Neckara Voir le message
    Sinon, 1 correspond à la sortie standard, mais il n'y a pas un define existant pour éviter d'écrire un nombre magique (nombre écrit en dur dans le programme) ?
    Euh oui, je crois que c'est STDOUT_FILENO...

    Citation Envoyé par edgarjacobs Voir le message
    Si la fonction est rectifiée comme tu le dis, on peut encore la simplifier
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void test(const char * buff, int length)
    {
        write(1, buff, length);
        printf("%d",length);
    }
    Ben comme j'ai dit, son discours était un peu fouilli et donc j'ai lu en diagonale. J'ai vu qu'il parlait de memcpy() et j'ai cru que c'était son but (le printf n'étant qu'un affichage de debug).
    En relisant mieux je vois qu'en fait, il voulait juste afficher le contenu de sa structure et que le memcpy() n'était qu'un moyen (moyen évidemment bien inutile)
    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
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    je veux dire par générique car ce paramètre elle prend n'importe quel type comme le void * mais de moi je préfere le char * car pour le char je vais manipuler les octets
    Je parle d'expérience, une telle fonction c'est de la merde à utiliser (il n'y a qu'à voir les versions Windows de send() et recv() qui exigent des casts vers char* sans aucune raison). Même si tu bosses en interne avec des char*, il faut que l'interface "exposée" par tes fonctions accepte des pointeurs void.
    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.

  9. #9
    Membre actif Avatar de fahdijbeli
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2012
    Messages : 281
    Points : 240
    Points
    240
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Je parle d'expérience, une telle fonction c'est de la merde à utiliser (il n'y a qu'à voir les versions Windows de send() et recv() qui exigent des casts vers char* sans aucune raison). Même si tu bosses en interne avec des char*, il faut que l'interface "exposée" par tes fonctions accepte des pointeurs void.
    oui effectivement je dois faire un driver wifi pou une carte électronique dans ce cas la je suis entrain de faire une bib comme socket.h de donc je suis entrain de faire des fonction send() et recv() . mais j'ai pas bien compris qu'est ce que ta dit , si j'ai compris je dois changer l'attribut vers void * ?

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par fahdijbeli Voir le message
    mais j'ai pas bien compris qu'est ce que ta dit , si j'ai compris je dois changer l'attribut vers void * ?
    Oui. Faut toujours te mettre dans l'hypothèse que tu ne travailles pas que pour toi mais aussi pour les autres. Ca rendra ton code plus souple, plus modulaire, mieux commenté, bref ça ne peut que l'améliorer.
    Et dans cette hypothèse, vaut mieux que ta fonction soit vraiment générique (accepter un void*) et que les casts éventuels soient faits en interne plutôt que de forcer les autres à faire un cast pour utiliser ta fonction.
    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]

  11. #11
    Membre actif Avatar de fahdijbeli
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2012
    Messages : 281
    Points : 240
    Points
    240
    Par défaut
    OK, d'accord je vais le changer et merci pour l'aide autre fois .

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

Discussions similaires

  1. Réponses: 12
    Dernier message: 12/12/2004, 14h25
  2. Réponses: 6
    Dernier message: 28/04/2004, 10h41
  3. Réponses: 3
    Dernier message: 01/02/2004, 21h24
  4. Informations sur les procédures stockées
    Par jfphan dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 13/01/2004, 14h30
  5. Réponses: 6
    Dernier message: 28/09/2003, 17h49

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