1

Comment manipule-t-on des nombres binaires ? Je sais qu'il faut, comme en Ti-Basic mettre un 0b devant les nombres. Mais :
Comment les déclarer ?
Est-ce que les opérations usuelles (+, -) marchent toujours avec des nombres binaires ?
Est-ce qu'il existe déjà des fonctions toutes faites permettant de passer de binaire à décimal et inversement, ou dois-je créer mes propres fonctions ? (j'ai cherché dans la documentation de TIGCC et je n'ai rien trouvé à ce sujet).

2

3

En fait, je dois remplir un tableau de 24 sur 24. Chaque case peut contenir un nombre. Mais j'aimerai que ce nombre soit "porteur" de 9 informations. Les informations sont binaires : soit vraies soit fausses.
Donc j'ai pensé fabriquer des nombres binaires de neufs chiffres (chaque chiffre donnant une information des 9 informations au total) : 011001110. Or ça peut aller jusqu'à 111111111. Je vais pas pouvoir remplir mon tableau avec des nombres aussi gigantesques que ça ! Si je les converti en décimal, c'est déjà beaucoup plus résonable : le maximum est donc de 551.
Donc après, au cours du jeu, rien qu'en lisant une case, j'obtient 9 informations directement en convertissant le nombre décimal en binaire et en analysant ce chiffre binaire !

4

la base n'est qu'une représentation comme l'a dit martial, ton nombre est toujours stocké en binaire dans la machine
apres si tu veux écrire des nombres en binaires, utilises le préfixe 0b
par exemple 0b111111111 = 511 (et pas 551 wink) mais ça ne change rien à part au niveau lisibilité
apres pour si tu veux acceder facilement à chaque bit de ton nombre tu as deux solutions :
- utuiliser les opérateurs binaires bit à bit & et | (à ne pas confondre avec && et ||)
- utiliser un champ de bit
tu déclare une structure et tu peux dire sur combien de bit doit tenir ta variable

struct toto {
short info1:1,info2:1,info3:1; //etc...
}

ainsi tes variables info1, 2 et 3 n'utiliseront qu'un seul bit
tu peux y acceder comme à n'importe quel membre d'une structure :

struct toto var;
var.info1 = 1;

en interne, le compilateur utilisera aussi les opérations & et | donc le choix d'une méthode dépend de comment tu veux utiliser ça
moi je te conseille plutot le champ de bits, c'est bien plus simple à manipuler et tu n'auras pas à t'emmerder avec des masques
avatar

5

Ok Nu. J'ai testé, mais j'ai un problème. J'ai mis :
struct toto {
short info1:1;
short info2:1;
short info3:1;
short info4:1;
short info5:1;
short info6:1;
short info7:1;
short info8:1;
short info9:1;} var;

var.info1 = 0;
var.info2 = 1;
var.info3 = 0;
var.info4 = 0;
var.info5 = 1;
var.info6 = 1;
var.info7 = 1;
var.info8 = 0;
var.info9 = 1;

Quand je met : printf("%d", var); ça m'affiche : 20096 : ce nombre correspond à quoi ?
Quand je met : printf("%d%d%d%d%d%d%d%d%d", var.info1, var.info2, var.info3, var.info4, var.info5, var.info6, var.info7, var.info8, var.info9); ça m'affiche 0-100-1-1-10-1 : d'où viennent ces tirets ?

Aussi, comment accéder dans une boucle qui incrémente une variable i de 1 à chaque fois, à var.info(i) ?

6

Tu n'as pas bien compris comment utiliser les champs de bits.
Voici comment déclarer ta structure :
struct s_champ_bits
{
  unsigned char bit0:1, bit1:1, bit2:1, bit3:1, bit4:1, bit5:1, bit6:1, bit7:1;
};

Ensuite, plus tard dans ton programme, tu peux instancier une variable de ce type :
struct s_champ_bits var;
var.bit2 = 1;
printf("%d",(unsigned int)var.bit2);
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

7

Cette fois-ci j'ai tapé :

struct toto {
unsigned char info1:1, info2:1, info3:1, info4:1, info5:1, info6:1, info7:1, info8:1, info9:1;
};

struct toto var;
var.info1 = 0; var.info2 = 1; var.info3 = 0; var.info4 = 0; var.info5 = 1; var.info6 = 1; var.info7 = 1; var.info8 = 0; var.info9 = 1;

Si je veux accéder à var.info9 par printf("%d", var.info9); par exemple, maintenant ça marche bien ça affiche bien 1.
Par contre, si je mets printf("%d", var); , là ça ne met pas ce à quoi je m'attends. De quel type est "var" ? C'est une suite de bits, donc un nombre binaire (010011101). Normalement ça devrait m'afficher 157, or là, ça met : 20113. Ou est l'erreur ?

J'ai une deuxième question : peut-on accéder à un bit i de var ? i étant variable bien sûr, par exemple à l'intérieur d'une boucle.

8

9

Wé, mais continuons dans les champs de bit : pourquoi ça affiche 20113 au lieu de 157 ? Ou je me suis trompé ? var est de quel type : un int ?

10

var est une structure.
Tu n'es pas censé connaître sa représentation interne.
Pour connaître le contenu de l'octet formé par tes bits, le C dispose d'un "type" intéressant : l'union.
ed char byte; };
En faisant ceci :union s_champ_bits
{
  struct
  {
    unsigned char bit0:1, bit1:1, bit2:1, bit3:1, bit4:1, bit5:1, bit6:1, bit7:1;
  };
 unsign

Tu peux maintenant lire l'octet formé par les bits en écrivant var.byte.
Note : dans ma déclaration, j'ai mis le bit0 en premier. Il ne faut pas le confondre avec le bit de poids faible qui est en fait nommé bit7.
J'aurais du dès le début bien déclarer ça, cela aurait été plus propre, mais bon...
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

11

C'est quoi le bit de poids faible ?
Tu es sûr que c'est bien ça le code ? Quand je le compile, TIGCC détecte erreurs : "Unnamed struct/union that defines no instances." et "Structure has no member named 'byte'."
J'ai mis ce bout de code après la déclaration, c'est bien ça ?

12

Moi je n'ai aucun pb à la compilation avec gcc 3.3.5.
Tu peux poster ton code exact ?
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

13

void _main(void)
{

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

struct s_champ_bits var; 

var.bit2 = 0;

union s_champ_bits 
{ 
  struct
  { 
    unsigned char bit0:1, bit1:1, bit2:1, bit3:1, bit4:1, bit5:1, bit6:1, bit7:1; 
  }; 
 unsigned char byte; 

};


ClrScr();
printf("%d",(unsigned int)var.byte);
ngetchx();

}

14

15

Mais là tu composes deux types différents avec le même nom... roll (l'union et la structure).
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

16

perso, je préfère les masques explicites comme en asm smile


[EDIT : cross sad]
tismaster> peut-être parce que ta struct et ton union ont le même nom ?

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

17

Pollux, oui mais peut-être que là le compilo peut optimiser certains cas particuliers d'accès ?
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

18

Sinon, vous pouvez me dire ce que vous appelez la "méthode des masques".
Je repose ma question initiale, pour pas trop s'éloigner du sujet : comment à partir d'un entier, accéder à chaque bit de son écriture binaire ?
Et la réciproque : connaissant la valeur de chaque bits de l'écriture binaire d'un entier, comment fabriquer cet entier ?

19

Sasume>

non, au contraire, c'est plutôt nettement plus délicat pour un compilo d'optimiser "bitfield.machin=1, bitfield.truc=0" en "bitfield.value = MACHIN"...

sans compter que c'est relativement fréquent que tous les champs d'un bitfield ne soient pas utiles au même moment, ce qui veut dire que
typedef struct {
  char is_a_file:1;    // est-ce un fichier ou un répertoire ?
  char is_a_program:1; // est-ce un programme ?
  char is_a_picture:1; // est-ce une image ?
  char is_collapsed:1; // est-ce que le répertoire est replié ?
} ItemType;

void set_itemtype(int type) {
  itemtype.is_a_file=1;
  itemtype.is_a_program=0;
  itemtype.is_a_picture=0;
  if (i->type==PICTURE)
    itemtype.is_a_picture=1;
  else if (type==PROGRAM)
    itemtype.is_a_program=1;
}

ne pourra pas être hyper bien optimisé, puisque certains champs ('is_collapsed' en l'occurrence) n'ont une signification que quand on parle d'un répertoire et pas d'un fichier. Mais le compilateur ne le sait pas, donc il doit impérativement se souvenir de l'ancienne valeur de 'is_collapsed' et la restaurer telle quelle...

Donc, dans le meilleur des cas, ça sera transformé en interne en un truc du genre de
void set_itemtype(int type) {
  itemtype.value = itemtype.value&~(MASK_PROGRAM|MASK_PICTURE) | MASK_FILE;
  if (i->type==PICTURE)
    itemtype.value |= MASK_PICTURE;
  else if (type==PROGRAM)
    itemtype.value |= MASK_PROGRAM;
}

alors que si on avait utilisé des masques directement on aurait pu faire
void set_itemtype(int type) {
  if (i->type==PICTURE)
    itemtype = MASK_FILE|MASK_PICTURE;
  else if (type==PROGRAM)
    itemtype = MASK_FILE|MASK_PROGRAM;
  else
    itemtype = MASK_FILE;
}

qui est très nettement plus efficace...

Et perso je trouve que la dernière formulation est plutôt plus lisible et compacte ^^



A part ça, je ne vois pas vraiment ce que tu pourrais faire comme optimisation sur les bitfields que tu ne pourrais pas faire avec les masques confus

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

20

tismaster :
Sinon, vous pouvez me dire ce que vous appelez la "méthode des masques".
Je repose ma question initiale, pour pas trop s'éloigner du sujet : comment à partir d'un entier, accéder à chaque bit de son écriture binaire ?
Et la réciproque : connaissant la valeur de chaque bits de l'écriture binaire d'un entier, comment fabriquer cet entier ?

Les "masques" ça correspond à ceci : si tu as un nombre x qui s'écrit 0bABCDEFGH, alors x & 0x20 = x & 0b00100000 = 0b00C00000, donc tu peux savoir si C vaut 0 ou 1 en regardant si x & 0x20 est nul ou pas smile
Inversement, tu peux mettre C à 1 en considérant tout simplement x | 0x20 = x | 0b00100000 = 0bAB1DEFGH, ou le mettre à 0 en considérant x & ~0x20 = x & 0b11011111 = 0bAB0DEFGH ^^

Et évidemment si tu veux un truc plus lisible que des constantes numériques partout tu peux faire
#define MASK_C 0x20

if (x & MASK_C)
  printf("le bit C est à 1\n");
int x_avec_c_valant_1 = x | MASK_C;
int x_avec_c_valant_0 = x & ~MASK_C;

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

21

Ok, finalement, je vais le faire avec les masques, ça me paraît beaucoup plus simple. En tout cas, merci à tout le monde !

22

Mais pourquoi ne pas utiliser des decalage de bit tout simplement...
sa te permettrait d'avoir acces a tes bits comme dans un tableau...

genre pour le bit 4:
octet & (1 << 4)...

ce ki me parait plus commode ke des mask en dure....

23

Avec la méthode de Pollux j'ai accès à mes bits comme dans un tableau. Les masques, je les obtiens par une petite formule simple en fonction de la case à tester donc ils sont pas en "dur".

24

./19 > OK, tu m'as convaincu merci smile

./22 > Ta méthode est la méthode des masques.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »