J'ai un peu de mal à saisir n bits d'un octet.
J'ai un entier non signé. Disons que notre nombre en hexadécimal est 0x2A, qui est 42 en décimal. En binaire, cela ressemble à ceci: 0010 1010. Comment saisir les 5 premiers bits qui sont 00101 et les 3 bits suivants qui sont 010, et les placer dans des entiers séparés?
Si quelqu'un pouvait m'aider, ce serait formidable! Je sais extraire d'un octet, c'est simplement faire
int x = (number >> (8*n)) & 0xff // n being the # byte
que j'ai vu sur un autre post sur le débordement de pile, mais je ne savais pas comment obtenir des bits séparés de l'octet. Si quelqu'un pouvait m'aider, ce serait génial! Merci!
Les entiers sont représentés à l'intérieur d'une machine comme une séquence de bits; heureusement pour nous les humains, les langages de programmation fournissent un mécanisme pour nous montrer ces nombres en décimal (ou hexadécimal), mais cela ne modifie pas leur représentation interne.
Vous devez réviser les opérateurs au niveau du bit &
, |
, ^
et ~
ainsi que les opérateurs de décalage <<
et >>
, qui vous aidera à comprendre comment résoudre des problèmes comme celui-ci.
Les 3 derniers bits de l'entier sont:
x & 0x7
Les cinq bits à partir du huit dernier bit sont:
x >> 3 // all but the last three bits
& 0x1F // the last five bits.
"saisir" des parties d'un type entier en C fonctionne comme ceci:
&
pour masquer les bits que vous voulez - uns signifie "copier ce bit", les zéros signifient "ignorer"Donc, dans votre exemple. Disons que nous avons un nombre int x = 42;
5 premiers bits:
(x >> 3) & ((1 << 5)-1);
ou
(x >> 3) & 31;
Pour récupérer les trois bits inférieurs:
(x >> 0) & ((1 << 3)-1)
ou:
x & 7;
Supposons que vous souhaitiez hi
bits en haut et lo
bits en bas. (5 et 3 dans votre exemple)
top = (n >> lo) & ((1 << hi) - 1)
bottom = n & ((1 << lo) - 1)
Explication:
Pour le en haut, débarrassez-vous d'abord des bits inférieurs (décalage à droite), puis masquez le reste avec un masque "tous les" (si vous avez un nombre binaire comme 0010000
, en soustrayant un résultat 0001111
- le même nombre de 1
s comme vous aviez 0
- s dans le numéro d'origine).
Pour le fond, c'est la même chose, ne vous souciez pas du décalage initial.
top = (42 >> 3) & ((1 << 5) - 1) = 5 & (32 - 1) = 5 = 00101b
bottom = 42 & ((1 << 3) - 1) = 42 & (8 - 1) = 2 = 010b
Vous pouvez utiliser des champs de bits pour cela. Les champs de bits sont des structures spéciales où vous pouvez spécifier des variables en bits.
typedef struct {
unsigned char a:5;
unsigned char b:3;
} my_bit_t;
unsigned char c = 0x42;
my_bit_t * n = &c;
int first = n->a;
int sec = n->b;
Les champs de bits sont décrits plus en détail sur http://www.cs.cf.ac.uk/Dave/C/node13.html#SECTION0013200000000000000
Le charme des champs de bits est que vous n'avez pas à vous occuper des opérateurs de décalage, etc. La notation est assez simple. Comme toujours avec la manipulation des bits, il y a un problème de portabilité.
int x = (number >> 3) & 0x1f;
vous donnera un entier où les 5 derniers bits sont les 8-4 bits de number
et des zéros dans les autres bits.
De même,
int y = number & 0x7;
vous donnera un entier avec les 3 derniers bits définissez les 3 derniers bits de number
et les zéros dans le reste.
débarrassez-vous simplement du 8 * dans votre code.
int input = 42;
int high3 = input >> 5;
int low5 = input & (32 - 1); // 32 = 2^5
bool isBit3On = input & 4; // 4 = 2^(3-1)