Как извлечь определенные биты из числа в C?
Мне нужно извлечь определенную часть (нет битов) типа данных short
в C.
Для примера у меня есть двоичный код 52504 как 11001101000 11000, и я хочу, чтобы первые 6 (FROM LSB → MSB i.e 011000 десятичных 24) битов и остальное 10 бит (11001101000 десятичное число 820).
Аналогично, я хочу, чтобы эта функция была слишком обобщенной, чтобы извлечь конкретное количество бит, заданное "start" и "end" (например, куски бит, эквивалентные некоторому десятичному значению).
Я проверил другие сообщения, но это не помогло, так как заданные функции не слишком обобщены.
Мне нужно что-то, что может работать для типа данных short
C.
Изменить
У меня есть короткий массив размером 2048 байт. Где каждый пиксель имеет 10 бит. Таким образом, мой 16 бит, состоящий из каждого байта, занимает некоторое время 2 пикселя данных, иногда 3 пикселя данных.
Как
(PIXEL: 0,1)
10 BITS + 6 BITS
затем (PIXEL: 1,2,3)
4 BITS (оставшиеся бит 1-го пикселя) + 10 BITS + 2 BITS.
и т.д. этот шаблон продолжается...
Итак, все, что я хочу, чтобы извлечь каждый пиксель и сделать целый массив, чтобы каждый пиксель был занят wholy в WHOLE BYTE (из 16 бит), как..
1 байт должен содержать 1 DIX PIXEL, другой BYTE должен содержать другое значение PIXEL всего 16 бит и т.д. И т.д.
Ответы
Ответ 1
Есть два строительных блока, которые вам нужно знать, чтобы создать их самостоятельно:
- Получение
N
младших значащих бит требует построения битовой маски с N
в конце. Вы делаете это так: ((1 << N)-1)
. 1 << N
2 ^ N
: он имеет один 1
в позиции N+1
st и все нули после него. Вычитая один, вы получите нужную вам маску.
- Отбрасывание
M
младших значащих бит - это простой сдвиг вправо: k >> M
Теперь ваш алгоритм для вырезания от M
до N
становится двухэтапным процессом: вы смещаете исходное значение M
bits вправо, а затем выполняете бит-мудрый 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
при запуске. Биты нумеруются с нуля.
Ответ 2
unsigned short extract(unsigned short value, int begin, int end)
{
unsigned short mask = (1 << (end - begin)) - 1;
return (value >> begin) & mask;
}
Обратите внимание, что [begin, end)
- это полуоткрытый интервал.
Ответ 3
Это можно сделать следующим образом:
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
, чтобы выровнять нужные бит влево.
Затем побитовое И дает результат.
Ответ 4
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
}
вы можете добавить параметры, чтобы получить значения или что-то
Ответ 5
// 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;
}
Ответ 6
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));
}
Ответ 7
Хотя это очень старый вопрос, я хотел бы добавить другое решение. Используя макросы,
/*
Вот, startBit: начало битовой позиции (счетчик из LSB) endBit: конечная позиция бит (счетчик из LSB).NOTE: endBit > startBit number: номер, из которого извлекаются биты 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
Ответ 8
//To get value from specific position 'pos' to 'pos+offset' in number 'value'
#define bitGet(value, offset, pos) (((1ull << offset) - 1) & (value >> (pos - 1)))
//Set value 'newval' from position 'pos' to 'pos+offset' in number 'value'
#define bitSet(value, offset, pos, newval) \
(~(((1ull << offset) - 1) << (pos - 1)) & value) | ((((1ull << offset) - 1) & newval) << (pos - 1))