it-roy-ru.com

Как извлечь конкретные биты из числа в C?

Мне нужно извлечь конкретную часть (без битов) типа данных short в C. 

Например, у меня есть двоичный код 52504 как 11001101000 11000, и я хочу первые 6 (ОТ LSB -> MSB, т.е. 011000 десятичных 24) битов и оставшиеся 10 бит (11001101000 десятичных 820).

Точно так же я хочу, чтобы эта функция была слишком обобщенной, чтобы извлекать определенное количество битов, заданных «начало» и «конец» (т.е. куски битов эквивалентны с некоторым десятичным значением).

Я проверил другие посты, но они не были полезны, поскольку данные функции не слишком обобщены.

Мне нужно что-то, что может работать для short типа данных C.

Правка

У меня есть короткий массив размером 2048 байт. Где каждый пиксель имеет 10 бит. Итак, мои 16 бит, состоящие из каждого байта, занимают некоторое время 2 пикселя данных, иногда 3 пикселя данных.

Подобно 

(ПИКСЕЛ: 0,1) 10 BITS + 6 BITS

затем (PIXEL: 1,2,3) 4 BITS (1-й пиксель, оставшиеся биты) + 10 BITS + 2 БИТА.

и так далее .. этот шаблон продолжается ... Итак, все, что я хочу, чтобы извлечь каждый пиксель и создать целый массив, состоящий из каждого пикселя, который должен быть занят целиком на целом байте (16 бит), например ..1 байт должен содержать 1 DATA PIXEL, другой BYTE должен содержать другое значение PIXEL в целых 16 битах и ​​так далее, и так далее.

18
Usman

Есть два строительных блока, которые вы должны знать, чтобы построить это самостоятельно:

  • Для получения N наименее значимых битов необходимо создать битовую маску с N в конце. Вы делаете это так: ((1 << N)-1). 1 << N - это 2 ^ N: он имеет один 1 в позиции N+1st и все нули после него. Вычитая один, вы получите маску, которая вам нужна.
  • Отбрасывание M младших разрядов - это простой сдвиг вправо: k >> M

Теперь ваш алгоритм вырезания из M в N становится двухэтапным процессом: вы сдвигаете исходное значение M битов вправо, а затем выполняете побитовое AND с маской из 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;
}

Этот фрагмент вырезает биты от 4, включительно, до 16, эксклюзив и печатает bee при запуске. Биты нумеруются с нуля.

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

Обратите внимание, что [begin, end) - это полуоткрытый интервал.

13
Andreas Brinck

Это можно сделать так:

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

где n - исходное целое число, а value - извлеченные биты.

mask построен так:

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

Теперь n сдвигается вправо на start биты для выравнивания желаемых битов влево . Затем побитовое И дает результат.

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
}

вы можете добавить параметры, чтобы получить значения или что-то

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

Хотя это очень старый вопрос, я хотел бы добавить другое решение. Используя макросы,

/*Вот, startBit: начальная позиция бита (отсчет от LSB) endBit: позиция конечного бита (отсчет от LSB). ПРИМЕЧАНИЕ: endBit> startBit номер: номер, из которого нужно извлечь биты maxLength: общий размер бит числа. */.__ `.

#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;
}

`

Результат: Входы: 1 5 255 32
Введите номер: 255
Результат: 62 

Здесь 255 = 11111111 и 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