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 :

C - Afficher valeur d'entier sous forme "machine"


Sujet :

C

  1. #1
    Nouveau membre du Club
    Inscrit en
    Juillet 2009
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 30
    Points : 33
    Points
    33
    Par défaut C - Afficher valeur d'entier sous forme "machine"
    Hello,

    Je viens pour vous demander un peu d'aide !

    En fait, je voudrait mettre en difference la gestion memoire sous les architechture little/big endian ! Pour cela, je voudrais afficher la valeur en binaire d'un nombre octet par octet ! Oui, c'est un peu confus ...

    En gros cree un unsigned int et je recupere son adresse dans un char * pour afficher octets par octet... le probleme c'est que ... ... ca ne fonctionne pas !!! Et je ne comprend pas pourquoi ! Un peu d'aide serait la bienvenue !

    Voil 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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    #include        <unistd.h>
     
    int             my_putchar(int c)
    {
      return (write(1, &c, 1));
    }
     
    void            test_conv(const unsigned int nbr)
    {
      char          *nbr_addr;
      unsigned int  mask;
     
      nbr_addr = (char *) &nbr;
      mask = 0x800000;
      while (mask)
        {
          my_putchar('0' + ((nbr & mask) != 0));
          mask >>= 1;
          if (mask == 0x80000 || mask == 0x8000 || mask == 0x800 || mask == 0x80 || mask == 0x8)
            my_putchar('\'');
        }
      my_putchar('\n');
    }
     
    void            aff_octet(const char nbr)
    {
      int           mask;
     
      mask = 0x8;
      while (mask)
        {
          my_putchar('0' + ((nbr & mask) != 0));
          mask >>= 1;
        }
    }
     
    void            aff_val(const unsigned int nbr)
    {
      char          *nbr_addr;
      unsigned int  mask;
     
      nbr_addr = (char *) &nbr;
      mask = 0xF00000;
      while (mask)
        {
          aff_octet(*nbr_addr++);
          mask >>=4;
          if (mask)
            my_putchar('\'');
        }
      my_putchar('\n');
    }
     
    int             main()
    {
      test_conv(0xFABC80);
      aff_val(0xFABC80);
      return (0);
    }
    resultat sous une archi little endian :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    /tmp $>cc endian.c -Wall -Wextra && ./a.out
    1111'1010'1011'1100'1000'0000
    0000'1100'1010'0000'0000'0011
    et big endian
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    > /usr/sfw/bin/gcc endian.c -o test
    > ./test
    1111'1010'1011'1100'1000'0000
    0000'1010'1100'0000'0000'0000
    D'avance, merci

  2. #2
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    aff_octet()
    Pourquoi appelles-tu ta fonction aff_octet() alors qu'elle n'affiche pas un octet mais 4 bits ? Pour tromper l'ennemi ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void aff_octet(const char nbr)
    {
      int mask;
      mask = 0x80 ; //<<<<< 0x8;
      while (mask)
        {
          my_putchar('0' + ((nbr & mask) != 0));
          mask >>= 1;
          if(mask == 0x8) my_putchar('\'');//<<<<<
        }
    }
    aff_val()
    - je suppose que tes entiers ne font pas 24 bits, mais 32. L'initialisation de mask est alors fausse.
    - Lorsqu'on passe d'un octet à l'autre, le masque doit être décalé de 8, pas de 4
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void aff_val(const unsigned int nbr)
    {
      char *nbr_addr;
      unsigned int mask;
      nbr_addr = (char *) &nbr;
      mask = 0xFF000000; //<<<<<< 0xF00000;
      while (mask)
        {
          aff_octet(*nbr_addr++);
          mask >>= 8;   //<<<<<<4;
          if (mask) my_putchar('\'');
        }
      my_putchar('\n');
    }
    test_conv()
    Si tes entiers font 32 bits, il faut corriger le masque et compléter le gros if()
    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
    void test_conv(const unsigned int nbr)
    {
      char *nbr_addr;
      unsigned int  mask;
      nbr_addr = (char *) &nbr;
      mask = 0x80000000;  //<<<<<< 0x800000;
      while (mask)
        {
          my_putchar('0' + ((nbr & mask) != 0));
          mask >>= 1;
          if (   mask == 0x8000000 || mask == 0x800000 // <<<<<<
              || mask == 0x80000   || mask == 0x8000 || mask == 0x800 || mask == 0x80 || mask == 0x8) 
            my_putchar('\'');
        }
      my_putchar('\n');
    }
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  3. #3
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 81
    Points : 128
    Points
    128
    Par défaut
    Je n'ai pas regardé ton code dans le détail.
    J'en ai écrit un autre qui affiche le nombre sous ça forme hexadécimale (suffisant pour démontrer l'organisation des octets) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        unsigned int nbr = 0xFA5C784E;
        size_t bcl = sizeof nbr;
        unsigned char* nbr_addr = (unsigned char*)&nbr;
     
        while (bcl--)
        {
            printf("%02X ", *nbr_addr++);
        }
    En sortie, j'obtiens ça :
    Précision : je suis sur un Pentium, donc sur une architecture little-endian.

  4. #4
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 81
    Points : 128
    Points
    128
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Oui mais cela est faux.
    L'inversion des bits est inversé. Ce n'est pas implement une inversion des octets.
    Sauf que l'unité de base d'accès à la mémoire est l'octet. Je ne vois pas comment démontrer la différence de représentation des données au niveau des bits avec un programme. C'est transparent pour l'utilisateur.

    Citation Envoyé par LittleWhite Voir le message
    Moi je propose, pour l'affichage d'un unsigned int:
    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
     
    void affUI(unsigned int valeur)
    {
        unsigned int i = 0;
        for ( i = 0 ; i < 32 ; i++ )
        {
            if ( valeur & 0x01 == 1 )
                printf("1");
            else
                printf("0");
     
            valeur =>> 1; // Décalage qui permet de passer au bit suivant
        }
     
        printf("\n");
    }
    (Attention, je n'ai pas testé)
    A priori, ta fonction affiche la valeur binaire d'un nombre du bit de poids faible au bits de poids fort sans tenir compte de l'organisation en mémoire.

  5. #5
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 580
    Points
    218 580
    Billets dans le blog
    120
    Par défaut
    Citation Envoyé par sam1507 Voir le message
    Sauf que l'unité de base d'accès à la mémoire est l'octet. Je ne vois pas comment démontrer la différence de représentation des données au niveau des bits avec un programme. C'est transparent pour l'utilisateur.
    A priori, ta fonction affiche la valeur binaire d'un nombre du bit de poids faible au bits de poids fort sans tenir compte de l'organisation en mémoire.
    Ah bah ... je viens de me rendre compte de mon erreur
    Donc oui ... mon message est faux
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  6. #6
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    le test le plus courant est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #define LITTLE_ENDIAN 0
    #define BIG_ENDIAN    1
     
    int machineEndianness()
    {
       int i = 1;
       char *p = (char *) &i;
       if (p[0] == 1) // Lowest address contains the least significant byte
          return LITTLE_ENDIAN;
       else
          return BIG_ENDIAN;
    }
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  7. #7
    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 ne comprend pas pourquoi la version "pointeur" utilise un masque. Normalement, soit on y va au masque, soit on y va au pointeur...

    Code C : 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
    void aff_vraie_valeur(int i)
    {
    	int num_octet = sizeof i;
    	do
    	{
    		num_octet--;
    		{
    			int decalage = CHAR_BIT * num_octet;
    			int valeur_octet = (i >> decalage) & 0x0FFu;
    			aff_octet(valeur_octet);
    		}
    	} while(num_octet!= 0);
    }
     
    void aff_representation_memoire(int i)
    {
    	int index;
    	unsigned char const *ptr = (unsigned char const *)&i;
     
    	for(index=0 ; index < sizeof i ; index++)
    		aff_octet(ptr[index]);
    }
    Sur une architecture big-endian, les valeurs devraient être identiques; sur une architecture little-endian, elles devraient être différentes.

    Bien sûr, pour que le programme puisse tester l'endianness, le mieux est la fonction de souviron34.
    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.

Discussions similaires

  1. [Débutant]Récuperer les valeurs de panel sous forme de matrice
    Par feather1 dans le forum Windows Forms
    Réponses: 3
    Dernier message: 19/02/2008, 18h09
  2. Affiché le fichier séléctionner sous forme de texte
    Par Jeremy0201 dans le forum Tkinter
    Réponses: 1
    Dernier message: 08/07/2007, 15h45
  3. Afficher un programme C sous forme d'un graphe
    Par progfou dans le forum Autres éditeurs
    Réponses: 3
    Dernier message: 28/02/2006, 17h03

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