web-dev-qa-db-ja.com

バイト配列に特定のビットを設定する

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、08}

ビットシフトの使用を検討しましたが、128ビットで構成される配列でビットシフトする方法について混乱しました。このサイズの配列を分解し、バイトの小さなチャンクで評価する方法はありますか?どんな助けでもいただければ幸いです。

8
Nevets

特定のビットを選択するプロセスは、次の2つのステップで構成されます。

  • バイトを選択してから
  • ビットを選ぶ。

バイトの選択は簡単です。必要なのは、ビットインデックスをバイト内のビット数で除算することです。つまり、8で除算するだけです。

int byteIndex = bitIndex / 8;

使用するバイトがわかったので、アクセスするビットを計算します。そのためには、次のように、除算の余りを8で計算する必要があります。

int bitInByteIndex = bitIndex % 8;

これらの2つのインデックスが手元にあれば、ビットに簡単にアクセスできます。use1 << 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;
23
dasblinkenlight

BitArrayを使用できます。

byte[] bytearray = new byte[16];

var bitArray = new BitArray(bytearray);

bitArray.Set(8, true);

bitArray.CopyTo(bytearray, 0);
13

バイト配列から直接、最も簡単な解決策はおそらくビット配列を使用することです。 - http://msdn.Microsoft.com/en-us/library/system.collections.bitarray.aspx

例えば。これは次のようになります。

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]);
}

これにはパフォーマンスの低下が伴います。

したがって、別の方法として、4バイトのブロックを整数に変換する必要があるBitVector32があります... 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;
    }
}
7
Jens

まず、使用しているバイトを見つける必要があります。あなたが持っているとしましょう:

00000000 00000000 00000000 00000000 ...

そして、10番目のビットをオンにしたいので、次のようにする必要があります。

00000000 01000000 00000000 00000000 ...

したがって、最初に8で除算(切り捨て)して、バイト番号(この場合はバイト番号1、つまり2番目のバイト)を見つけます。それが済んだら、ビット演算子を使用して必要なビットを設定できます。

array[1] |= 0x40

そのバイトの古い値と0x40(01000000)の間でビット単位のOR演算を実行しています)。古い値が00101101の場合、array[1] = (00101101 OR 01000000)、つまり01101101

当然、この場合、私はリテラルを使用しているので、設定されているビットに応じてリテラルを変更する必要があります(たとえば、最後のビットより前のビットを設定している場合は、代わりに0x02を使用します。 。

2
Gigi

ビット数を8で割ると、バイトが得られます。 8を法として、バイト内のビット番号を取得します。

1
Ronald

次のように、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];
0
storojs72