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 :

Je ne comprend pas le résultat de ce code


Sujet :

C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2017
    Messages : 11
    Points : 27
    Points
    27
    Par défaut Je ne comprend pas le résultat de ce code
    Bonjour,
    Voici ce que contient ma fonction main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char buf[1024] = "put 394c8a052d ::1";
      char get_or_put[3];
      int j;
      for (j = 0; j < 3; j++) get_or_put[j] = buf[j];
      printf("%s\n", get_or_put);
    Et j'obiens comme résultat : "puput 394c8a052d ::1", je ne comprend vraiment pas pourquoi j'ai ce résultat.

    Bonne journée et merci d'avance.

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Comment pourrait-on déterminer la fin de la chaîne que tu cherches à afficher ?

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2017
    Messages : 11
    Points : 27
    Points
    27
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Comment pourrait-on déterminer la fin de la chaîne que tu cherches à afficher ?
    J'essaye simplement de copier les trois premiers caractères de buf dans get_or_put. L'affichage est censé me donner 'put'

  4. #4
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Alors je reformule ma question initiale : comment printf pourrait-il déterminer que la chaîne que tu lui présentes contient trois octets, et pas deux ou six ?

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2017
    Messages : 11
    Points : 27
    Points
    27
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Alors je reformule ma question initiale : comment printf pourrait-il déterminer que la chaîne que tu lui présentes contient trois octets, et pas deux ou six ?
    D'accord, étant donné que sa taille est de trois je pense qu'il doit en afficher trois non ?

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Comment détermine-t-il que la taille est trois?
    Sachant qu'un argument de fonction n'est jamais un tableau, mais un pointeur.

    Qu'est-ce qu'une chaine de caractère en C?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  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 984
    Points
    30 984
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Fahya Voir le message
    D'accord, étant donné que sa taille est de trois je pense qu'il doit en afficher trois non ?
    Bonjour

    Ben non. Le C n'est pas assez évolué pour faire ce rapprochement. D'ailleurs ce serait assez malheureux qui'il bosse de cette façon parce qu'alors l'affichage de "buf" afficherait 1024 caractères (tu aurais pu t'en rendre compte tout seul !!!)
    Pour afficher une chaine, il part du début de la chaine et boucle jusqu'à ce qu'il trouve la "fin de la chaine". A toi de reprendre ton cours sur "ce qu'est une chaine de caractères en C" (cf post de ternel) pour comprendre comment il trouve cette "fin de chaine"...
    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
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2017
    Messages : 11
    Points : 27
    Points
    27
    Par défaut
    Je sais ce qu'est une fin de chaîne. Mais j'ai vu dans tous mes cours que si on fait printf("%s\n", chaine); cela affichait la chaine. Je n'ai pas besoin d'afficher buf justement, je veux juste récupérer ses trois premiers caractères en les copiant dans une chaîne. J'ai tout de même suivi vos conseils en ajoutant dans ma fonction "get_or_put[3] = '\0'", mais cela ne marche toujours pas.

  9. #9
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Citation Envoyé par Fahya Voir le message
    je veux juste récupérer ses trois premiers caractères en les copiant dans une chaîne
    Alors sprintf est la solution : sprintf(copy,"%.3s", chaine);
    D’ailleurs si ton but est seulement d'afficher 3 caractère alors printf("%.3s\n", chaine);

    Par contre :
    Citation Envoyé par Fahya Voir le message
    J'ai tout de même suivi vos conseils en ajoutant dans ma fonction "get_or_put[3] = '\0'", mais cela ne marche toujours pas.
    Il faudrait faire une révision des tableaux en C !
    Quand tu déclare get_or_put[3] , cela veut dire qu'il existe : get_or_put[0] , get_or_put[1] , get_or_put[2] et donc écrire sur get_or_put[3] c'est un buffer overflow donc oui normal que cela ne marche pas !

  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 984
    Points
    30 984
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Fahya Voir le message
    Je sais ce qu'est une fin de chaîne.
    Certainement. Mais tu n'as pas fait le rapprochement entre "ce que tu sais" et ton code et c'est ce qu'on te reproche. Autrement dit en plus condensé: si tu le sais, pourquoi tu ne l'as pas mis ?
    Citation Envoyé par Fahya Voir le message
    Mais j'ai vu dans tous mes cours que si on fait printf("%s\n", chaine); cela affichait la chaine.
    Effectivement, quand tu as une vraie chaine, contenant toutes les caractéristiques appropriées d'une chaine, alors printf("%s\n", chaine) ça l'affiche proprement. Malheureusement "get_or_put" ce n'est pas une chaine donc printf("%s\n", get_or_put) ça ne te l'affiche pas proprement.
    Ainsi, le résultat de ton code correspond exactement à ce qui est indiqué dans tous tes cours (ou plutôt à ce qu'on peut en déduire parce que, en logique mathématique, si A implique B, alors non(B) implique non(A) => si j'ai une chaine alors printf("%s\n", chaine) l'affiche proprement donc si printf("%s\n", get_or_put) ne l'affiche pas proprement c'est que c'est pas une chaine)...
    Citation Envoyé par Fahya Voir le message
    Citation Envoyé par Sve@r Voir le message
    ...parce qu'alors l'affichage de "buf" afficherait 1024 caractères
    Je n'ai pas besoin d'afficher buf justement,
    Je ne te parlais pas réellement d'afficher buf (t'as pas remarqué le conditionnel de "afficherait" ?). Je te donnais cet exemple pour te montrer que ton hypothèse "si la taille de ma variable est de trois ça affiche trois caractères" ne tenait pas la route parce que pour buf la taille est de 1024 donc si on affichait buf ça afficherait (là aussi un conditionnel) 1024c !!!
    Citation Envoyé par Fahya Voir le message
    je veux juste récupérer ses trois premiers caractères en les copiant dans une chaîne.
    Oui on a bien compris. Le problème, c'est que tu ne les copies pas dans une "chaine" mais dans un simple "tableau" !!!!!!!!!
    Citation Envoyé par Fahya Voir le message
    J'ai tout de même suivi vos conseils en ajoutant dans ma fonction "get_or_put[3] = '\0'"
    Là ça commence à venir. Mais si tu y réfléchis, tu devrais te rendre compte que "nos" conseils suivent la logique. Si une chaine c'est un tableau contenant impérativement quelque part un '\0' ; mais que rien dans ton code ne prouve qu'un des éléments du tableau "get_or_put" vaut '\0', alors c'est qu'il n'y est pas et qu'il faut le mettre.
    Citation Envoyé par Fahya Voir le message
    mais cela ne marche toujours pas.
    Voir post de Kannagi. 'p', 'u', 't' et '\0' ne peuvent pas tenir dans un char[3] et ça aussi tu aurais pu t'en rendre compte tout seul (au pire compter avec tes doigts...)
    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
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Citation Envoyé par ternel Voir le message
    Comment détermine-t-il que la taille est trois?
    Sachant qu'un argument de fonction n'est jamais un tableau, mais un pointeur.

    Qu'est-ce qu'une chaine de caractère en C?
    La réponse à la première question est: pas.
    Une adresse ne désigne pas un tableau, mais un de ses éléments. On peut toujours calculer des adresses d'éléments du même type, et voisins.
    Par exemple, si p est un pointeur (un argument de fonction) vers un type T, alors (p+1) et (p-4) sont aussi des pointeurs vers des T.
    Mais rien ne peut dire à la fonction qu'il y a bien un T à cet endroit là.
    Du coup, la fonction peut manipuler la mémoire à cet endroit, aveuglément.
    C'est ce défaut qui est la cause/raison des failles de sécurité de type "buffers overflow" (et gets() a été retirée du langage pour cette raison précise).

    Il n'y a que trois solutions possibles:
    • Prendre la taille en argument supplémentaire.
    • Utiliser une valeur sentinelle. La mémoire pointée est valide dans une direction donnée (généralement, ++), tant qu'on ne tombe pas dessus.
    • Avoir la taille intégrée dans la zone mémoire (en premier élément, peut-être, ou dans la structure donnée en argument)


    Les fonctions manipulant des chaines parcourent la mémoire jusqu'à tomber sur un '\0'.
    Cela signifie que pour pouvoir être utilisées, il faut s'assurer qu'un '\0' est en place.
    Dans ton cas, ce n'est pas le cas.

    Je peux même dire que ton système est compilé avec une pile dont le haut est dirigé vers les adresses basses.
    Dans la pile, le second tableau est placé au dessus du premier. C'est à dire aux adresses juste inférieures, et jointives.
    Comme tu n'as pas de '\0' à la fin du petit tableau, la fonction continue à parcourir. Manque de chance pour toi, il tombe sur une autre chaine "valide".
    Avec un peu de chance, tu affichais de la mémoire arbitraire.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  12. #12
    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 984
    Points
    30 984
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ternel Voir le message
    Citation Envoyé par Fahya Voir le message
    Et j'obiens comme résultat : "puput 394c8a052d ::1"
    Dans la pile, le second tableau est placé au dessus du premier. C'est à dire aux adresses juste inférieures, et jointives.
    J'y avais pensé aussi. Je me suis même dit qu'avec ce code il était totalement impossible d'avoir comme résultat "puput 394c8a052d ::1" et que le résultat réel était probablement "putput 394c8a052d ::1"...

    Citation Envoyé par ternel Voir le message
    Avec un peu de chance, tu affichais de la mémoire arbitraire.
    Personnellement je pense plutôt que ça c'est de la malchance et que la chance c'est d'avoir un "segfault" montrant ainsi qu'il y a un gros souci ; plutôt que d'avoir un programme qui ne plante pas et qui, tout en montrant éventuellement le bug, continue à tourner et à produire des résultats faux...
    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]

Discussions similaires

  1. Explain : je ne comprends pas le résultat
    Par Zachatim dans le forum Requêtes
    Réponses: 4
    Dernier message: 06/01/2016, 01h42
  2. Je ne comprend pas le résultat du programme
    Par sk8trasher dans le forum Débuter
    Réponses: 2
    Dernier message: 22/10/2012, 16h39
  3. Alors là j'comprends pas le résultat de cette requête.
    Par mouche dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 27/02/2008, 10h14
  4. Réponses: 2
    Dernier message: 12/01/2007, 01h27
  5. Réponses: 22
    Dernier message: 16/08/2006, 13h11

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