将数组中的任意位复制到变量中?

时间:2019-08-28 21:01:57

标签: c++ arrays bit memcpy

所以我正在处理以数组形式出现的数据集。例如:

{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,但这只能是字节可寻址的。

我将不胜感激!

2 个答案:

答案 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);

Live Demo

如果需要,您可以进一步优化它,以使代码一次移位+复制一次超过1位。例如,在进入循环之前,如果起始位索引不在字节边界,则将不需要的位从初始的bOR的剩余位移到Result。然后将循环OR的整个1个字节循环到Result中,同时所需的位数为>= 8。然后,在退出循环后,如果所需的位数仍为> 0,则将不需要的位数从最后的bOR的剩余位数移到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