web-dev-qa-db-fra.com

Récupération de n bits dans un octet

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!

17
user1871869

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.
21
rici

"saisir" des parties d'un type entier en C fonctionne comme ceci:

  1. Vous déplacez les bits que vous souhaitez à la position la plus basse.
  2. Tu utilises & 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;
13
Mats Petersson

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 1s 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
8
gaborsch

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é.

6
wirrbel

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.

2
meyumer

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)
1
Dave