Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

OBTENIR L'ETAT DES BITS QUI COMPOSENT UN OCTET (CONVERSION XX->BINAIRE)


Information sur la source

Catégorie :Astuces Classé sous : bin, binaire, convertir, convertion, union Niveau : Débutant Date de création : 14/12/2005 Vu : 9 333

Note :
7,5 / 10 - par 2 personnes
7,50 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (21)
Ajouter un commentaire et/ou une note

Description

J'ai regardé très rapidement si la source n'existait pas et je ne l'ai pas trouvé.
Je précise que c'est une astuce que je viens d'apprendre en cours.
En utilisant "Les champs de bits" et une union, nous pouvons très simplement obtenir l'état des bits qui composent un octet... mais pourquoi pas un int en modifiant un peu le code.
Les champs de bits :
   Pour se qui ne connaisse pas, ils permettent de limiter la place occupé en mémoire d'une variable si tous ces bits ne sont pas utilisés.
   Pour représenter cela il suffit de mettre après le nom de la variable :nombre_bit
   Par exemple, int état:1;   //ici l'int ne fera pas 32bits mais qu'un seul, les valeurs max et min de etat seront donc -1 ou 0
union
   A la différence d'un struct, les éléments contenus dans une union sont contenu au même emplacement mémoire
   (La structure les met à la suite dans la mémoire)
   Je me doute que se n'ai pas très clair un exemple:
   struct _test{
       int a;
       unsigned char b;
   }
   Ici la structure occupera 5octets en mémoire (sizeof(int)=4octets et sizeof(char)=1octet)

   union _test2{
       int a;
       unsigned char b;
   }test2;
   Ici sizeof(test2)=4octet
   si
   test2.a=0xFDE8;     //valeur prise au hasard
   Alors
   b=0xE8;

Schéma de la mémoire:

  structure                 union
|-----------|           |-----------|
|           |           |           |
|     a     |           |   a et b  |
|           |           |           |
|-----------|           |-----------|
|     b     |
|-----------|

J’espère que c'est clair.
Revenons au but...créer une union entre un caractère et une structure et lire la structure pour avoir l'état des bits, regardez le code.

Les champs de bits ne sont pas toujours obligatoires.
Autre utilisation de l'union :
#include <stdio.h>

union _ip{
unsigned char membres[4]; //Les 4 membres qui compose une adresse IP
unsigned int adIp; //L'adresse IP au complet
}ip;

main()
{
printf("saisir une adresse ip en hexa :");
scanf("%x",&ip.adIp); //Saisie en hexa de l'adresse ip au complet

printf("l'adresse ip est : %03d.%03d.%03d.%03d\n"
,ip.membres[3],ip.membres[2],ip.membres[1],ip.membres[0]); //Attention a l'ordre,il est inversé
}
 

Source

  • #include <stdio.h>
  • typedef unsigned char uchar; //evite de récrire le tout
  • /*Ma structure qui contiendra l'etat de chacun des bit qui compose un char*/
  • typedef struct{
  • uchar b0:1; //Poid faible
  • uchar b1:1;
  • uchar b2:1;
  • uchar b3:1;
  • uchar b4:1;
  • uchar b5:1;
  • uchar b6:1;
  • uchar b7:1; //Poid fort
  • }octet;
  • /*Mon union qui me permet de superposer les variable 'valeur' et 'etat'*/
  • union _mot{
  • char valeur;
  • octet etat;
  • }mot;
  • /*Mon main qui me permet de tester*/
  • main()
  • {
  • printf("saisir une valeur (de -128 a +127):"); //Valeur max d'un char signé
  • scanf("%d",&mot.valeur);
  • printf("sizeof(octet) = %d\n",sizeof(octet)); //Montre l'interait des champ de bits 1 octet au lieu de 8
  • printf("sizeof(mot) = %d\n",sizeof(mot)); //Montre que l'union superpose bien les deux variables et ne les met pas à la suite
  • printf("Etat b0: %d\n",mot.etat.b0);
  • printf("Etat b1: %d\n",mot.etat.b1);
  • printf("Etat b2: %d\n",mot.etat.b2);
  • printf("Etat b3: %d\n",mot.etat.b3);
  • printf("Etat b4: %d\n",mot.etat.b4);
  • printf("Etat b5: %d\n",mot.etat.b5);
  • printf("Etat b6: %d\n",mot.etat.b6);
  • printf("Etat b7: %d\n",mot.etat.b7);
  • }
#include <stdio.h>

typedef unsigned char uchar;	//evite de récrire le tout

/*Ma structure qui contiendra l'etat de chacun des bit qui compose un char*/
typedef struct{
	uchar b0:1;		//Poid faible
	uchar b1:1;
	uchar b2:1;
	uchar b3:1;
	uchar b4:1;
	uchar b5:1;
	uchar b6:1;
	uchar b7:1;		//Poid fort
}octet;

/*Mon union qui me permet de superposer les variable 'valeur' et 'etat'*/
union _mot{
	char valeur;
	octet etat;
}mot;

/*Mon main qui me permet de tester*/
main()
{
	printf("saisir une valeur (de -128 a +127):");   //Valeur max d'un char signé
	scanf("%d",&mot.valeur);

	printf("sizeof(octet) = %d\n",sizeof(octet));    //Montre l'interait des champ de bits 1 octet au lieu de 8
	printf("sizeof(mot) = %d\n",sizeof(mot));        //Montre que l'union superpose bien les deux variables et ne les met pas à la suite

	printf("Etat b0: %d\n",mot.etat.b0);
	printf("Etat b1: %d\n",mot.etat.b1);
	printf("Etat b2: %d\n",mot.etat.b2);
	printf("Etat b3: %d\n",mot.etat.b3);
	printf("Etat b4: %d\n",mot.etat.b4);
	printf("Etat b5: %d\n",mot.etat.b5);
	printf("Etat b6: %d\n",mot.etat.b6);
	printf("Etat b7: %d\n",mot.etat.b7);
}

Commentaires et avis

signaler à un administrateur
Commentaire de TanKu le 14/12/2005 23:52:48

Désolé pour le schéma de la mémoire je voulais que sa donne cela :

  structure.......union
|-----------| |-----------|
|...........| |...........|
|.....a.....| |...a et b..|
|...........| |...........|
|-----------| |-----------|
|.....b.....|
|-----------|
(j'ignore se que sa va donné....)

signaler à un administrateur
Commentaire de ymca2003 le 15/12/2005 11:20:40

Pour information, autre source en relation :
http://www.cppfrance.com/code.aspx?ID=10065

signaler à un administrateur
Commentaire de BruNews le 15/12/2005 11:44:28 administrateur CS

Les bases du langage C sont à considérer comme acquises.
struct, union etc... se trouvent dans les 1ers chapitres de tout bouquin correct.

signaler à un administrateur
Commentaire de neria le 15/12/2005 13:11:23

Pour obtenir l'état des bits, on peux aussi faire un masque. Par exemple pour obtenir l'état du bit 3 (en partant de la droite) il faut faire :
    variable & 4    
Car 4 en binaire c'est 00000100b

@+

signaler à un administrateur
Commentaire de BruNews le 15/12/2005 13:18:46 administrateur CS

C'est dans tous les cas ce que le compilo mettra en code, il n'y a aucun autre moyen car la plus petite entité adressable est l'octet, le bit est seulement manipulable.

signaler à un administrateur
Commentaire de zeratul67 le 15/12/2005 20:40:57

Une utilisation intéressante, lorsque vous ne maitrisez pas l'octet dont vous voulez manipuler les bits (que vous ne pouvez pas directement le déclarer comme étant un union):

typedef struct
{
unsigned char bit0 : 1,
bit1 : 1,
bit2 : 1,
bit3 : 1,
bit4 : 1,
bit5 : 1,
bit6 : 1,
bit7 : 1;
} bit_field;

#define Bit(octet) (*(volatile bit_field *) (&(octet)))

SOURCE : http://anyedit.free.fr/

signaler à un administrateur
Commentaire de CyberP le 19/12/2005 08:12:19

pourquoi faire simple quand on peut faire compliqué hein ?
personnelement j'ai beaucoup plus simple :

int main() {
  unsigned char valeur;
  printf("saisir une valeur (de -128 à +127):");
  scanf("%d", &valeur);

  printf("Etat b0: %d\n", (valeur & 1) ? 1 : 0);
  printf("Etat b1: %d\n", (valeur & 2) ? 1 : 0);
  printf("Etat b2: %d\n", (valeur & 4) ? 1 : 0);
  printf("Etat b3: %d\n", (valeur & 8) ? 1 : 0);
  printf("Etat b4: %d\n", (valeur & 16) ? 1 : 0);
  printf("Etat b5: %d\n", (valeur & 32) ? 1 : 0);
  printf("Etat b6: %d\n", (valeur & 64) ? 1 : 0);
  printf("Etat b7: %d\n", (valeur & 128) ? 1 : 0);

  return 0;
}

comme tu expliques les struct et les unions, je vais aussi expliquer ce que je fais :

c'est comme ce que dit neria plus haut (sauf qu'il s'agit du bit numéro 2, dans toutes les docs techniques tu trouveras que le premier bit est le numéro 0)
si la valeur est 52 par exemple (ce qui fait 110100 en binaire)
on fait par exemple 52 & 16 :
00110100
00010000  // ça c'est 16
00010000  // ça c'est le résultat
en effet, le & met un 1 là où les bits des deux nombres (des deux opérandes) sont tous les deux égaux à 1 et de même poids (au même rang), sinon il met 0

donc 52 & 16 donne 16
en fait le résultat ne peut être que 16 ou 0 (si on y réfléchit un peu), c'est-à-dire que si le résultat du & est 16, le bit numéro 4 (le bit le plus à droite est le numéro 0) sera égal à 1, sinon à 0
donc je fais tout simplement (52 & 16) ? 1 : 0  ce qui fait que si 52 & 16 vaut 0, le résultat final sera 0, sinon le résultat final sera 1

on pourrait aussi faire des décalages de bits pour ramener la valeur à 1
ou même diviser par 16 tout simplement (un 0 donnerait toujours 0 et un 16 donnerait 1)
le plus rapide reste le décalage de bits :
(52 & 16) >> 4

signaler à un administrateur
Commentaire de Arnaud16022 le 19/12/2005 12:20:23

perso ce que je fais c'est de shifter le registre vers la droite jusqu'a ce que le bit qui m'intéresse soit de poids faible et en 2 masques c'est réglé

char ORmask =(char)0xFE;
char ANDmask=(char)0x01;
bit=((octet>>num_bit|ORmask)&ANDmask;

signaler à un administrateur
Commentaire de CyberP le 19/12/2005 16:45:11

euh d'après moi ça fonctionne pas ce truc
n'importe quel nombre où tu fais "or 0xFE" suivi de "and 0x01" sera nul parce que le or met le premier bit à 0 et le and ne garde que le premier bit
(maintenant faudrait voir l'ordre de priorité des opérateurs, peut être que le or s'exécute avant le décalage de bits et là ça donnerait un truc encore plus buggé)

il suffit de supprimer le or
bit = (octet >> num) & 1

signaler à un administrateur
Commentaire de VinceVG le 08/05/2006 17:07:03

pourquoi faire simple quand on peut faire compliqué hein ?
personnelement j'ai beaucoup plus simple :

int main() {
  unsigned char valeur;
  printf("saisir une valeur (de -128 à +127):");
  scanf("%d", &valeur);

  printf("Etat b0: %d\n", (valeur & 1) ? 1 : 0);
  printf("Etat b1: %d\n", (valeur & 2) ? 1 : 0);
  printf("Etat b2: %d\n", (valeur & 4) ? 1 : 0);
  printf("Etat b3: %d\n", (valeur & 8) ? 1 : 0);
  printf("Etat b4: %d\n", (valeur & 16) ? 1 : 0);
  printf("Etat b5: %d\n", (valeur & 32) ? 1 : 0);
  printf("Etat b6: %d\n", (valeur & 64) ? 1 : 0);
  printf("Etat b7: %d\n", (valeur & 128) ? 1 : 0);

  return 0;
}


Je n'appel pas ça plus simple. En plus le code qu'a rapporté Zeratul est destiné à la programmation sur des µC, il est donc simple et Zen (je veux dire peux couteux en ressources). Il permet l'accés au bit des ports et registre quand le compilateur ne le permet pas.

signaler à un administrateur
Commentaire de zeratul67 le 08/05/2006 18:00:08

Pour information, j'ai fais quelques tests de compilation avec Visual Studio (VC++.NET 2003 v7.1.3088)

Le grand classique avec masque : bit = variable & 8;
donne en code machine :
mov         eax,dword ptr [variable]
and         eax,8
mov         dword ptr [bit],eax

Ma solution, qui est plus lisible dans le code source : bit = Bit(variable).bit3;
mov         al,byte ptr [variable]
shr         al,3
and         al,1
movzx       ecx,al
mov         dword ptr [bit],ecx

Le code résultant est plus volumineux, et ce sans raison que je comprenne. Conclusion : il vaut mieux utiliser un masque :(

(en écriture de bit, les deux codes "Bit(variable).bit3 = 1;" et "variable |= 8;" donnent e même code machine, ce qui est bien plus logique).

Je vous encourage à tester avec d'autres compilos ... (j'ai actuellement un soucis avec mon GCC, si j'y pense je vous communiquerai les résultats)

signaler à un administrateur
Commentaire de VinceVG le 09/05/2006 10:07:15

Voilà une intéressante démarche.

signaler à un administrateur
Commentaire de Melodie_Nelson le 11/05/2006 11:37:35

bonjour,
je dois commander un LCD en parallèle à partir d'un LPC. il y'a donc 8 bits de Data à gérer ainsi que 3 bits d'instructions.
et donc je commande mon paramètre Data en hexa, ke je dois donc ensuite transformer pour avoir l'état de mes 8 bits. si j'ai compris le truc, est-ce que c'est corect comme ça ?


void  data (void) //transformer une valeur hexa en 8 bits pour DO à D7

{
typedef struct
{
unsigned char   LCD0 : 1,
LCD1 : 1,
LCD2 : 1,
LCD3 : 1,
LCD4 : 1,
LCD5 : 1,
LCD6 : 1,
LCD7 : 1;
} LCD_bit;

#define Bit(octet) (*(volatile LCD_bit *) (&(octet)))


}

donc si j'ai compris ça doit être ça. et donc "octet" est ma variable data ?
bon je suis assez septik en fait, j'ai peur de rien comprendre

signaler à un administrateur
Commentaire de VinceVG le 12/05/2006 15:09:09

Oui

signaler à un administrateur
Commentaire de Melodie_Nelson le 15/05/2006 10:19:04

A Oui ?  

Mais oui quoi ?

signaler à un administrateur
Commentaire de VinceVG le 15/05/2006 10:36:42

est-ce que c'est corect comme ça ?

oui

signaler à un administrateur
Commentaire de Melodie_Nelson le 15/05/2006 15:31:56

bien, merci mais je pense faire autrement finalement

sinon j'ai une autre question, qui n'a rien à voir certes.

c'est pour obtenir le nombre de caractère d'un mot. sachant que je n'ai pas les librairies telle stdio ou string.

est-ce correct comme ça ??

[code]
int n=0;
while(word[n]!=0)
n++ ;  //n est donc le nombre de caractère de word
[/code]

signaler à un administrateur
Commentaire de BruNews le 15/05/2006 15:38:45 administrateur CS

Va bon.

signaler à un administrateur
Commentaire de Melodie_Nelson le 15/05/2006 16:00:33

Merci.
Pfffou, j'en chie.
Tant qu'on y est j'ai une autre question ( enfin j'en ai des millions mais bon ).
Euh, comment dire, donc je commande mon LCD à partir d'un LPC2138. Et je ne sais pas comment assigner mes 8 bits de data du LCD. Je vais les commander en hexa.
Par ex : lcd_data(0x38)
donc ensuite ma procédure lcd_data(infodata) doit transformer ce code hexa pour assigner les 8 bits.
J'ai un peu du mal à expliquer parce que je ne comprends pas le problème.
Voici en gros mon programme :

union IO_PORT
{
u16 W;
u32 DW;
struct
{
u08 LSB;
u08 MLSB;
u08 MMSB;
u08 MSB;
} B2DW;
//etc

//l'afficheur est câblé sur les ports P0.16 à 23, ce qui correspond à B2DW.MMSB

//et on trouve aussi ça dans le fichier LPC_io.h :
#define IDE_PORT_L IO_IO1PIN->B2DW.MMSB


//ensuite :

void  init_aff(void)  /*faire l'init de l'afficheur*/
{
int i,j=0 ;
for(i=0;i<3;i++)
{
lcd_data(0x38);
delay(20000);
}

lcd_data (0x0C) ;
delay(20000);

//etc
}

void  lcd_data (char infodata)
{

IO0CLR = LCD_RS ; //mode instruction du LCD
IO0CLR = LCD_RW ; //mode écriture du LCD

IO0DIR = 0xFEFFB705; //  D0 à D7 en sortie

IDE_PORT_L = infodata ;
enable(80);  // validation pendant tant de ns
}

Où est le problème ? Pourquoi ça ne marche pas ?
C'est peut-être un problème  au niveau du lcd, je respecte peut-ête mal les procédures d'envoie de données. Voici sa doc http://www.spezial.de/doc/cctech/cmc216-01.pdf
Enfin je pense que c'est ma définition IDE_PORT_L qui n'est pas bonne.

signaler à un administrateur
Commentaire de VinceVG le 16/05/2006 11:39:20

On en chie tous le c est un anti language. Il doit rester réservé à des élus. On passe tellement de temps à apprendre à l'utiliser qu'aprés... une fois qu'on est dans le clan on refuse les autres outils avec dédain. je te dis ça j'ai commencer à programmer en hexa (et oui) puis en assembleur puis en basic (le vieu truc pourris) puis en gw basic. Et d'un coup j'ai commencé à respirer avec le pascal en enfin visual basic. Maintenant je suis punis et doit rétrograder au c.

Pour ton pb : si tu envoies le mot (qqs sa base) sur le port, ça devrait marcher  sans pb. Ton compilateur s'en charge.Je ne connait pas le lpc2138 ni le compilateur que tu utilise mais bon je n'en connait pas pour lesquels ça ne marche pas.

Ceci dit j'interviens aussi sur un autre forum, plus dédié à ce type d'utilisation du c. L'avantage c'est que la bas tout le monde est électronicien et donc tu auras des réponses rapides et pointus.

Je te met l'adresse : http://forums.jelectronique.com/



signaler à un administrateur
Commentaire de Melodie_Nelson le 17/05/2006 09:48:25

OK,
Mais en fait c'est bon j'ai réussi à régler ce problème. Mais j'en ai d'autres du coup maintenant.
Je vais donc aller voir sur jelectronique, merci

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

conversion decimal binaire sans connaitre la taille du nombre [ par kobee12 ] Est ce que quelqu'un pourrait m'aider. Voici un algo qui convertit un nombre binaire en decimal :bin_digits est defini avec une taille de 10. Or j'aim Convertir Binaire > decimal et pas l'inverse [ par hop ] Bonjour,J'ai cherché dans le forum comment faire pour convertir un mot binaire en décimal (dans cet ordre et pas dans l'autre)et je n'ai pas trouvé do Convertion Binaire => Decimal => Hexa... [ par WebKiller17 ] Hello a tous,J suis un amateur en prog... et j aurai besoin de votre coup de main... est ce que vous pourriez me dire ce qui joue pas dans ce code et Conversion Binaire->Chaine et Chaine->Binaire [ par Rouliann ] Bonjour &#224; tous!Voil&#224; mon probl&#232;me : je veux convertir une couleur de 24 bits en une couleur 15bits...Le seul moyen que j'ai trouv&#233; convertir un float en binaire [ par tiess81 ] Bonjour je suis en train de concevoir un interpreteur avec flex et bison qui doit me permettre de faire des calculs arithm&#233;tique dans toutes les Convertion [ par c_raf ] bonjour a tous,Je suis nouveau ici et pour me presenter je suis etudiant en bts informatique.Je post cette petite question car je dois creer realiser Convertir un fichier Binaire en Fichier Texte [ par brute ] bonjour a tous, J'ai un probl&#232;me, j'aimerais convertir un fichier binaire en fichier texte ..... Quelqu'un sait comment faire ?? Please help saisie d'un d'une expression arithmétique dans un arbre binaire [ par wlocity ] salut à tous, je suis nouveau sur ce forum, il est vraimment génial, merci ceux qui l'ont creervoilà, alors, mon problème ce résume à une fonction de coment convertir un fichier texte en fichier binaire [ par infodaoudi ] Bonjour,existe il une fonction qui converti un fichier texte par example composé de float séparé par des espaces (example 1.2 3.2 2.5...) en un fichie convertir un caractères en binaire [ par BAHROUNRABII ] bonjours tous,  Je  suis débutant en Programmation et je veut créer en langage C un prog qui permet de convertir un message txt en binaire... en p


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :

Comparez les prix Nouvelle version


LG KP501

Entre 9€ et 159€


Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,577 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.