web-dev-qa-db-fra.com

Comment extraire des bits spécifiques d'un nombre en C?

J'ai besoin d'extraire une partie spécifique (nombre de bits) d'un type de données short en C. 

Par exemple, j'ai un binaire de 52504 comme 11001101000 11000 et je veux d'abord 6 (FROM LSB -> MSB c'est-à-dire 011000 décimal 24) bits et reste de 10 bits (11001101000 décimal 820).

De même, je souhaite que cette fonction soit trop généralisée pour extraire un nombre spécifique de bits, à savoir "début" et "fin" (c'est-à-dire des morceaux de bits équivalents avec une valeur décimale).

J'ai vérifié d'autres messages, mais ceux-ci n'étaient pas utiles, car les fonctions données ne sont pas trop généralisées.

J'ai besoin de quelque chose qui peut fonctionner pour le type de données short de C.

Modifier

Je vais avoir le tableau court de taille 2048 octets. Où chaque pixel est de 10 bits. Donc, mes 16 bits consistant en chaque octet occupant quelque temps 2 données de pixels, parfois 3 données de pixels.

Comme 

(PIXEL: 0,1) 10 BITS + 6 BITS

puis (PIXEL: 1,2,3) 4 BITS (premiers pixels restants en pixels) + 10 BITS + 2 BITS.

et ainsi de suite ... Ce modèle continue ... Donc, tout ce que je veux extraire chaque pixel et faire un tableau entier de chaque pixel à être occupé complètement sur WHOLE BYTE (de 16 bits) comme ..1 octet doit contenir 1 DATA PIXEL, l'autre BYTE doit contenir une autre valeur PIXEL en 16 bits entiers, etc.

18
Usman

Vous devez connaître deux blocs de construction pour le construire vous-même:

  • Obtenir N bits les moins significatifs nécessite de construire un masque bit avec N à la fin. Vous le faites comme ceci: ((1 << N)-1). 1 << N est 2 ^ N: il a un seul 1 à la position N+1st et tous les zéros après. En soustrayant on vous donne le masque dont vous avez besoin.
  • Supprimer M bits les moins significatifs est un simple décalage vers la droite: k >> M

Maintenant, votre algorithme de découpage de M à N devient un processus en deux étapes: vous déplacez la valeur originale M bits vers la droite, puis effectuez une binaire AND avec le masque de N-M.

#define LAST(k,n) ((k) & ((1<<(n))-1))
#define MID(k,m,n) LAST((k)>>(m),((n)-(m)))

int main() {
    int a = 0xdeadbeef;
    printf("%x\n",  MID(a,4,16));
    return 0;
}

Ce fragment coupe les bits de 4 inclus, à 16, exclusif, et affiche bee lorsque vous l'exécutez. Les bits sont numérotés à partir de zéro.

24
dasblinkenlight
unsigned short extract(unsigned short value, int begin, int end)
{
    unsigned short mask = (1 << (end - begin)) - 1;
    return (value >> begin) & mask;
}

Notez que [begin, end) est un intervalle semi-ouvert.

13
Andreas Brinck

Cela peut être fait comme ça:

mask = ~(~0 << (end - start + 1));
value = (n >> start) & mask;

n est l'entier d'origine et value est les bits extraits.

La mask est construite comme ceci:

1. ~0 = 1111 1111 1111 1111 1111 1111 1111 1111
2. ~0 << (end - start + 1) = 1111 1111 1111 1111 1100 0000 0000 0000
   // assuming we are extracting 14 bits, the +1 is added for inclusive selection
   // ensure that end >= start
3. ~(~0 << (end - start + 1)) = 0000 0000 0000 0000 0011 1111 1111 1111

Maintenant, n est décalé à droite de start bits pour aligner les bits désirés sur la gauche .

7
0605002
void  f(short int last, short int first, short int myNr){
      //construct mask for last bits
      short int mask=0;
      for(int i=0;i<last;i++)
       { mask+=1;
        mask<<1;}
      short int aux= myNr;
      aux=aux&mask; // only last bits are left
      //construct mask for first bits
      mask=0;
      for(int i=0;i<first;i++)
       { mask+=0x8000h;
        mask>>1;} 
      aux=myNr;  
      aux&=mask;
      aux>>last; // only first bits are left and shifted
}

vous pouvez ajouter des paramètres pour obtenir les valeurs ou quelque chose

0
CosminO
// This is the main project file for VC++ application project 
// generated using an Application Wizard.

#include "stdafx.h"

#using <mscorlib.dll>

using namespace System;


void fun2(int *parr)
{
    printf(" size of array is %d\n",sizeof(parr));
}
void fun1(void)
{
    int arr[100];
    printf(" size of array is %d\n",sizeof(arr));
    fun2(arr);
}

int extractBit(int byte, int pos) 
{
    if( !((pos >= 0) && (pos < 16)) )
    {
        return 0;
    }
    return ( ( byte & (1<<pos) ) >> pos);
}
int extractBitRange(int byte, int startingPos, int offset) 
{


   if(  !(((startingPos + offset) >= 0) && ( (startingPos + offset) < 16)) )
   {
        return 0;
   }
   return ( byte >> startingPos ) & ~(0xff << (offset + 1));
}

int _tmain()
{
    // TODO: Please replace the sample code below with your own.

    int value;
    signed int res,bit;
    signed int stPos, len;
    value = 0x1155;
    printf("%x\n",value);
    //Console::WriteLine("Hello World");
    //fun1();
    for(bit=15;bit>=0;bit--)
    {
        res =extractBit(value,bit);
        printf("%d",res);
    }
    stPos = 4;
    len = 5;
    res = extractBitRange(value, stPos, len);
    printf("\n%x",res);

    return 0;
}
0
kapilddit

Bien que ce soit une question très ancienne, je voudrais ajouter une solution différente. Utiliser des macros,

/*Ici, startBit: position du bit de départ (compte à partir de LSB) endBit: position du bit de fin (nombre à partir du LSB). NOTA: endBit> startBit numéro: le nombre à partir duquel extraire des bits maxLength: la taille totale en bits du nombre. */ `

#include <stdio.h>
#define getnbits(startBit,endBit,number,maxLength) \
  ( number &  ( (~0U >> (maxLength-endBit)) & (~0U << startBit) )  ) 

int main()
{
    unsigned int num=255;
    unsigned int start=1,end=5,size=sizeof(num)*8;

    printf("Inputs : %d %d %d %d \n ",start,end,num,size);
    printf("Input number : %d\n",num);

    if(end>start)
    {
        int result = getnbits(start,end,num,size-1);
        printf("Output : %u\n\n",result);
    }
    else
        printf("Error : EndBit is smaller than starBit!\n\n");

    return 0;
}

`

Sortie: Entrées: 1 5 255 32
Numéro d'entrée: 255
Sortie: 62 

Ici, 255 = 11111111 et 62 = 00111110

0
PraveenMax
unsigned int extract_n2mbits(unsigned int x, int n, int m)
{
unsigned int mask, tmp;
if (n < m) {
    n = n + m;
    m = n - m;
    n = n - m;
}
mask = 1 << (n - m + 1);
tmp = m;
while (tmp > 1) {
    mask = mask << 1 | 1 << (n - m + 1);
    tmp = tmp - 1;
}
return ((x & mask) >> (n - m + 1));
}
0
user1596193