我需要在 C 中提取
short
数据类型的特定部分(位数)。
例如,我有一个二进制 52504 为 11001101000 11000,我想要前 6 位(从 LSB --> MSB 即 011000 十进制 24)位和其余 10 位(11001101000 十进制 820)。
同样,我希望这个函数过于笼统,无法提取给定“开始”和“结束”的特定位数(即与某个十进制值等效的位块)。
我检查了其他帖子,但那些没有帮助,因为给定的功能不太通用。
我需要一些可以适用于 C 的
short
数据类型的东西。
我有大小为 2048 字节的短数组。其中每个像素为 10 位。所以我的 16 位由每个字节组成,有时占用 2 个像素数据,有时占用 3 个像素数据。
喜欢
(像素:0,1) 10 位 + 6 位
然后(像素:1,2,3) 4 BITS(第一个像素剩余位)+ 10 BITS + 2 BITS。
等等..这种模式仍在继续...... 所以,我想提取每个像素并制作一个完整的数组,让每个像素完全占据整个字节(16 位),就像...... 1 个字节应包含 1 个数据像素,另一个字节应包含整个 16 位的其他像素值,依此类推。
您需要了解两个构建块才能自己构建它:
N
最低有效位需要构造一个 位掩码,末尾有 N
。你这样做:((1 << N)-1)
。 1 << N
是 2 ^ N
:它在第 1
第一个位置有一个 N+1
,其后全是零。减去 1 即可得到所需的蒙版。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
。位从零开始编号。
unsigned short extract(unsigned short value, int begin, int end)
{
unsigned short mask = (1 << (end - begin)) - 1;
return (value >> begin) & mask;
}
注意
[begin, end)
是半开区间。
可以这样做:
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
位,以将所需位左对齐。
然后按位 AND 给出结果。
//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))
虽然这是一个非常老的问题,但我想添加一个不同的解决方案。使用宏,
/* 这里, startBit : 起始位位置(从 LSB 开始计数) endBit : 结束位位置(从 LSB 开始计数)。注意: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
// 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;
}
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
}
您可以添加参数来获取值或其他东西
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));
}
我知道这是一个非常古老的问题,但显然仍然相关。这是我使用
((1 << N)-1)
技巧来获取所需位掩码的贡献。这里没有询问,但我将提供两种提取和“存储”所需位的方法。假设 someValue
在位 0-1 处保存一个名为 foo
的 2 位字段,在位 3-5 处保存一个名为 bar
的 3 位字段。让我们进一步假设您有一个代码生成器将偏移量硬编码到 setter 和 getter 中以简化界面,因为您当然这样做了。uint8_t someValue = 0;
inline uint8_t getFoo() const {
//start bit = 0, size in bits = 2, end = 2
uint8_t mask = (1 << (2 - 0)) - 1; //end-start-1
return (someValue >> 0) & mask; //shift back by start
}
inline void setFoo(uint8_t foo) {
someValue &= ~(((1 << (2 - 0)) - 1) << 0); //end-start-1, shift by start
someValue |= foo << 0; //shift by start
}
inline uint8_t getBar() const {
//start bit = 3, size in bits = 3, end = 6
uint8_t mask = (1 << (6 - 3)) - 1; //end-start-1
return (someValue >> 3) & mask; //shift back by start
}
inline void setBar(uint8_t bar) {
someValue &= ~(((1 << (6 - 3)) - 1) << 3); //end-start-1, shift by start
someValue |= bar << 3; //shift by start bit
}