在字节数组中设置特定位

时间:2014-01-28 14:20:32

标签: c# arrays bit-shift

我想知道如何在16字节数组(128位)中设置特定位。

例如......如果我想在数组中设置第9位,我希望:

{00,80,00,00,00,00,00,00,00,00,00,00,00,00,00,00}

如果我想设置第125位...

<00> 00,00 00,00,00,00,00,00,00,00,00,00,00,00,000}

我已经研究过使用位移,但是对于如何使用由128位组成的数组进行位移而感到困惑。有没有办法打破这个大小的数组并以较小的字节块进行评估?任何帮助将不胜感激。

6 个答案:

答案 0 :(得分:22)

选择特定位的过程包括两个步骤:

  • 选择字节,然后
  • 挑选一下。

拾取字节很简单:您需要做的就是将位索引除以字节中的位数 - 即除以8:

int byteIndex = bitIndex / 8;

现在您知道要使用的字节,请计算您要访问的位。为此你需要计算除法的余数,如下所示:

int bitInByteIndex = bitIndex % 8;

有了这两个索引,就可以轻松访问该位:使用1 << bitInByteIndex作为掩码,如下所示:

byte mask = (byte)(1 << bitInByteIndex);
bool isSet = (bytes[byteIndex] & mask) != 0;
// set to 1
bytes[byteIndex] |= mask;
// Set to zero
bytes[byteIndex] &= ~mask;
// Toggle
bytes[byteIndex] ^= mask;

答案 1 :(得分:13)

您可以使用BitArray:

byte[] bytearray = new byte[16];

var bitArray = new BitArray(bytearray);

bitArray.Set(8, true);

bitArray.CopyTo(bytearray, 0);

答案 2 :(得分:7)

直接来自字节数组,您最快的解决方案可能是使用BitArray。   - http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx

E.g。这将是:

public void BitManimulation() 
{
    //Ill just use 2 bytes here for demonstration, get your 16 bytes here.
    byte[] bytes = new[] { (byte)250, (byte)250 };

    //Convert your bytes to a BitArray.
    BitArray array = new BitArray(bytes);
    array[3] = !array[3]; // Flip
    array[4] = false; // 0
    array[5] = true; // 1

    //Convert back to bytes.
    byte[] bytes2 = new byte[2];
    array.CopyTo(bytes2,0);

    Console.WriteLine(bytes2[0]);
    Console.WriteLine(bytes2[1]);
}

现在这会带来性能损失。

所以作为替代方案,你有BitVector32需要你将4个字节的块转换为整数...   - http://msdn.microsoft.com/en-us/library/system.collections.specialized.bitvector32.aspx

最后你可以进行位移,XOR等以产生所需的结果。既然@dasblinkenlight已经给那个病人留下了一个很好的答案,那就让你解释一下。^

以下是基于他的帖子的一些快速帮助方法:

public static class ByteArrayExt
{
    public static byte[] SetBit(this byte[] self, int index, bool value)
    {
        int byteIndex = index / 8;
        int bitIndex = index % 8;
        byte mask = (byte)(1 << bitIndex);

        self[byteIndex] = (byte)(value ? (self[byteIndex] | mask) : (self[byteIndex] & ~mask));
        return self;
    }

    public static byte[] ToggleBit(this byte[] self, int index)
    {
        int byteIndex = index / 8;
        int bitIndex = index % 8;
        byte mask = (byte)(1 << bitIndex);

        self[byteIndex] ^= mask;
        return self;
    }

    public static bool GetBit(this byte[] self, int index)
    {
        int byteIndex = index / 8;
        int bitIndex = index % 8;
        byte mask = (byte)(1 << bitIndex);

        return (self[byteIndex] & mask) != 0;
    }
}

答案 3 :(得分:1)

将位数除以8会得到字节。以模8为模可以得到字节内的位数。

答案 4 :(得分:1)

首先,您需要找出您正在使用的字节。假设你有:

00000000 00000000 00000000 00000000 ...

你想要打开第10位,所以它需要变成这样:

00000000 01000000 00000000 00000000 ...

所以首先用8除法(向下舍入)来定位字节数(在这种情况下是字节编号1或第二个字节)。完成后,您可以使用按位运算符来设置所需的位,即

array[1] |= 0x40

我们在该字节的旧值和0x40(即01000000)之间进行按位OR运算。如果旧值为00101101,则array[1] = (00101101 OR 01000000),即01101101

当然,在这种情况下,我一直在使用文字,所以你必须根据设置的位来改变它(例如,如果你在最后一位之前设置位,你想使用0x02等等。

答案 5 :(得分:0)

您还可以使用lookUp,如下所示:

byte[] lookUp = { 1, 2, 4, 8, 16, 32, 64, 128 };

以下代码(考虑以字节为单位的反向位数)

int bytePosition = bitIndex / 8;
int bitInBytePosition = bitIndex % 8;
if (bitIndex < 8)
{
    bitInBytePosition = bitIndex;
}

array[bytePosition] ^= lookUp[7 - bitInBytePosition];