所以我正在处理以数组形式出现的数据集。例如:
{0x00、0x00、0xFF,0xF1、0x6D,0xA2、0x00 0x00}
{0b00000000、0b00000000、0b11111111、0b11110001、0b01101101、0b10100010、0b00000000、0b00000000}
我需要能够基于两个值从此数组中提取信息:
例如,如果起始位为17,位长为13(假设第一位为索引0),则我的数据为:
0b1111111111100
十进制:8188
该十进制值(或uint32_t或w / e)将存储在变量中并输出。我可以在单个情况下做到这一点,但是很难编写代码,其中起始位和位数是函数或代码块中的变量...
我尝试使用memcpy,但这只能是字节可寻址的。
我将不胜感激!
答案 0 :(得分:1)
从所需的起始位索引开始,您可以使用/
和%
运算符来计算数组中的确切字节以及该字节中的初始位索引。然后,只需迭代字节数组并四处移动位,直到将所需的位数复制到结果中即可。
例如:
uint32_t getBits(const void *Data, uint32_t DataLen, uint32_t StartBit, uint8_t NumBits)
{
uint32_t Result = 0;
// are there any bytes at all?
if (DataLen != 0)
{
// get a pointer to the starting byte...
const uint8_t *pData = &(static_cast<const uint8_t*>(Data)[StartBit / 8]);
uint8_t b = *pData;
// calculate the starting bit within that byte...
int BitOffset = 7 - (StartBit % 8);
// iterate for the desired number of bits...
for(int i = 0; i < NumBits; ++i)
{
// make room for the next bit...
Result <<= 1;
// copy the bit...
Result |= ((b >> BitOffset) & 0x01);
// reached the end of the current byte?
if (--BitOffset < 0)
{
b = *(++pData); // go to the next byte...
BitOffset = 7; // restart at the first bit in that byte...
}
}
}
// all done...
return Result;
}
uint8_t arr[] = {0x00, 0x00, 0xFF, 0xF1, 0x6D, 0xA2, 0x00, 0x00};
uint32_t value = getBits(arr, 8, 17, 13);
如果需要,您可以进一步优化它,以使代码一次移位+复制一次超过1位。例如,在进入循环之前,如果起始位索引不在字节边界,则将不需要的位从初始的b
和OR
的剩余位移到Result
。然后将循环OR
的整个1个字节循环到Result
中,同时所需的位数为>= 8
。然后,在退出循环后,如果所需的位数仍为> 0
,则将不需要的位数从最后的b
和OR
的剩余位数移到Result
。 / p>
我把它留作练习供您弄清楚。
答案 1 :(得分:0)
@Punchki如果您想自己制造一台机器,可以想到这个想法。
First (17) Last (inclusive)
! !
! ! +- The least significant bit in the least significant byte
! ! !
00000000 00000000 11111111 11110001 01101101 10100010 00000000 00000000
& & <- AND
01111111 11111100 <- 13 bit bit-mask
<- cast all bytes to std::uintmax_t and ...
<<(24-2) <<(16-2) <<(8-2) >>(0+2) <- ... shift and ...
| <- ... OR all into the result variable
00011111 11111100