将17位数据组合成字节数组

时间:2011-05-20 00:02:15

标签: c bytearray bit-manipulation

我尝试将17位数据组移动到字节数组时遇到了一些问题。我不想一步一步地走,但我无法弄清楚逻辑循环 我需要这种方式,因为我打算通过在合并它们之后将所有字节值相加来计算校验和。
所以这就是我正在努力的方向。

我有16个字节的数组。数组的前3个字节包含我之后的17位。 ([0]的8位,[1]的8位和[2]的MSB。)

我需要将这16个17位值移动到一个单独的字节数组中。

第一个很简单:

int index = 0;
myArray[index++] = driverData[driver][0];            //First byte
myArray[index++] = driverData[driver][1];            //Second byte
myArray[index] = (driverData[driver][2] & 0x80) << 7;  //First bit of the third byte.

从这里开始,尝试任何类型的循环都会越来越难以移动它们。

driver++;<br>
//Take the 7 MSBs from the data array.
myArray[index++] |= (byte)(driverData[driver][0] & 0x7e >> 1);
//This leaves a single bit left over on driverData[driver][0].
myArray[index] = (byte)(driverData[driver][1] & 0x1 << 7);

我想你得到的照片。我做错了吗?有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分:2)

听起来你有一个足够大的素数循环,使个别情况的编码成为一个坏主意。这是一个经典的包装问题。你需要一个循环遍历目的地的循环,以及一些内部代码,它们可以获得更多的数据包。您的打包代码应该知道上次迭代可以使用多少位,需要多少位,并且如果源指针不够,应该能够增加源指针。

答案 1 :(得分:2)

好的,所以这看起来很有效。我可能需要更多地测试它,但这似乎给了我迄今为止所期望的结果。我确信我能以某种方式做得更好。

// ... //
void foo()
{
    //Lets start by getting all the 17bit values from each driver for the board.
    int bitIndex = 7;
    int byteIndex = 0;
    int stopIndex = chipIndex + GetChipCount();
    //Now we start the shiftyness.
    for (int driver = chipIndex; driver < stopIndex; driver++) {
        int userBits =
            (driverData[driver][0] & 0xff) << 9 | (driverData[driver][1]
                               & 0xff)
            << 1 | (driverData[driver][2] & 0x80) >> 7;
        AddBitsToArray(userBits, ref bitIndex, ref byteIndex);

    }
}

/// <summary>
/// Takes the 17 bits, and adds them to the byte array.
/// </summary>
private void AddBitsToArray(int userBits, ref int bitIndex, ref int byteIndex)
{
    int bitCount = 17;
    while (bitCount > 0) {
        //First 8 bytes.
        checksumBytes[byteIndex] |=
            (byte) (((userBits & bitValue(bitCount - 1)) >>
                 (bitCount - 1)) << bitIndex);
        //Move up the bit index to be written to.
        bitIndex--;
        //Decrement the number of bits left to shift.
        bitCount--;
        //If we have gone past the 8th bit, reset the bitIndex and increment the byteIndex.
        if (bitIndex >= 0)
            continue;
        bitIndex = 7;
        byteIndex++;
    }
}

/// <summary>
/// Returns the value of a single bit at the given index.
/// </summary>
private int bitValue(int bitIndex)
{
    return (int)(Math.Pow(2, bitIndex));
}

答案 2 :(得分:1)

这是我想出的。该方法的第一部分只是设置一些虚假的输入数据,所以删除它并根据需要添加参数。 OutputData数组不必要地大,但我没有花时间计算它的实际长度。

我使用170作为输入值10101010并且有助于验证。

private void BitShift17()
{
    const int NumChunks = 16;
    byte[] DriverData = new byte[]
        {
            170,
            170,
            170
        };
    byte[][] InputData = new byte[NumChunks][];
    for (int n = 0; n < NumChunks; n++)
        InputData[n] = DriverData;

    byte[] OutputData = new byte[NumChunks * 3]; // Unnecessarily large

    int OutputIndex = 0;
    int BitPosition = 0;
    for (int Driver = 0; Driver < InputData.Length; Driver++)
    {
        for (int InputIndex = 0; InputIndex < 3; InputIndex++)
        {
            byte InputByte = InputIndex == 2 ? (byte)(InputData[Driver][InputIndex] & 128) : InputData[Driver][InputIndex];
            if (BitPosition == 0)
            {
                OutputData[OutputIndex] = InputByte;
                if (InputIndex == 2)
                    BitPosition++;
                else
                    OutputIndex++;
            }
            else
            {
                if (InputIndex == 2)
                {
                    OutputData[OutputIndex] |= (byte)(InputByte >> BitPosition);
                    BitPosition++;
                }
                else
                {
                    OutputData[OutputIndex] |= (byte)(InputByte >> BitPosition);
                    OutputIndex++;
                    OutputData[OutputIndex] = (byte)(InputByte << 8 - BitPosition);
                }
            }
        }
        if (BitPosition > 7) BitPosition = 0;
    }
}