C#语言:改变字节中的前四位

时间:2011-07-16 19:00:55

标签: c# bit-manipulation

为了充分利用字节,我试图将两个唯一值存储到一个字节中:一个在前四位中,另一个在后四位中。但是,我发现,虽然这种做法允许优化内存分配,但它使得更改存储在字节中的各个值变得困难。

在我的代码中,我想要改变一个字节中的第一组四位,同时保持同一字节中后四位的值。虽然按位运算允许我轻松检索和操作前四位值,但我发现很难将这个新值与一个字节中的第二组四位连接起来。问题是,如何从一个字节中擦除前四位(或者更准确地说,将它们全部置零)并添加新的4位组以替换刚刚擦除的四位,从而保留最后4位改变前四个字节时的字节位数?

以下是一个例子:

//  Changes the first four bits in a byte to the parameter value
public void changeFirstFourBits(byte newFirstFour)
{
    //  If 'newFirstFour' is 0101 in binary, make 'value' 01011111 in binary, changing
    //  the first four bits but leaving the second four alone.
}

private byte value = 255; // binary: 11111111

9 个答案:

答案 0 :(得分:19)

使用按位AND(&)清除旧位,将新位移位到正确位置并按位OR(|)将它们组合在一起:

value = (value & 0xF) | (newFirstFour << 4);

以下是发生的事情:

                       value        : abcdefgh
                       newFirstFour : 0000xyzw

                               0xF  : 00001111
                       value & 0xF  : 0000efgh
                  newFirstFour << 4 : xyzw0000
(value & 0xF) | (newFirstFour << 4) : xyzwefgh

答案 1 :(得分:12)

当我不得不这样做时,我会为我做一个readonly结构。当然,一个四位整数称为nybble:

struct TwoNybbles
{
    private readonly byte b;
    public byte High { get { return (byte)(b >> 4); } }
    public byte Low { get { return (byte)(b & 0x0F); } {
    public TwoNybbles(byte high, byte low)
    {
        this.b = (byte)((high << 4) | (low & 0x0F));
    }

然后在TwoNybbles和byte之间添加隐式转换。现在,您可以将任何字节视为具有高字节和低字节,而不会在主线代码中添加所有那些丑陋的字符。

答案 2 :(得分:2)

首先使用value & 0xF屏蔽高四字节。然后使用newFirstFour << 4将新位移到高四位,最后使用二进制或。将它们组合在一起。

public void changeHighFourBits(byte newHighFour)
{
    value=(byte)( (value & 0x0F) | (newFirstFour << 4));
}

public void changeLowFourBits(byte newLowFour)
{
    value=(byte)( (value & 0xF0) | newLowFour);
}

答案 3 :(得分:1)

我不确定你的方法应该做什么,但这里有一些方法:

void setHigh(ref byte b, byte val) {
    b = (b & 0xf) | (val << 4);
}

byte high(byte b) {
    return (b & 0xf0) >> 4;
}

void setLow(ref byte b, byte val) {
    b = (b & 0xf0) | val;
}

byte low(byte b) {
    return b & 0xf;
}

应该是不言自明的。

答案 4 :(得分:1)

public int SplatBit(int Reg, int Val, int ValLen, int Pos)
{
    int mask = ((1 << ValLen) - 1) << Pos;
    int newv = Val << Pos;
    int res = (Reg & ~mask) | newv;
    return res;            
}

示例:

  • Reg = 135
  • Val = 9(ValLen = 4,因为9 = 1001)
  • Pos = 2

  • 135 = 10000111

  • 9 = 1001
  • 9&lt;&lt; Pos = 100100
  • 结果= 10100111

答案 5 :(得分:0)

快速查看表明按位,可以使用&amp;运营商。所以要删除你应该能够做到的前四个字节:

byte value1=255; //11111111
byte value2=15; //00001111

return value1&value2;

答案 6 :(得分:0)

假设newVal包含您要在origVal中存储的值。 对4个最低有效位执行此操作:

byte origVal = ???;
byte newVal = ???
orig = (origVal & 0xF0) + newVal;

这是4个最重要的位:

byte origVal = ???;
byte newVal = ???
orig = (origVal & 0xF) + (newVal << 4);

答案 7 :(得分:0)

我知道你具体要求清除前四位,已经多次回答,但是我想指出,如果你有两个值&lt; = decimal 15,你可以简单地将它们组合成8位这样:

    public int setBits(int upperFour, int lowerFour)
    {
        return upperFour << 4 | lowerFour;            
    }

结果将是xxxxyyyy其中

xxxx = upperFour
yyyy = lowerFour

这就是你似乎想要做的事情。

答案 8 :(得分:0)

这是一些代码,但我认为之前的答案会为你做。这只是为了展示一些复制和过去的测试代码到一个简单的控制台项目中(WriteBits方法有帮助):

static void Main(string[] args)
    {
        int b1 = 255;
        WriteBits(b1);

        int b2 = b1 >> 4;
        WriteBits(b2);

        int b3 = b1 & ~0xF ;
        WriteBits(b3);

        // Store 5 in first nibble
        int b4 = 5 << 4;
        WriteBits(b4);

        // Store 8 in second nibble
        int b5 = 8;
        WriteBits(b5);

        // Store 5 and 8 in first and second nibbles
        int b6 = 0;
        b6 |= (5 << 4) + 8;
        WriteBits(b6);

        // Store 2 and 4 
        int b7 = 0;
        b7 = StoreFirstNibble(2, b7);
        b7 = StoreSecondNibble(4, b7);
        WriteBits(b7);

        // Read First Nibble
        int first = ReadFirstNibble(b7);
        WriteBits(first);

        // Read Second Nibble
        int second = ReadSecondNibble(b7);
        WriteBits(second);
    }

    static int ReadFirstNibble(int storage)
    {
        return storage >> 4;
    }

    static int ReadSecondNibble(int storage)
    {
        return storage &= 0xF;
    }

    static int StoreFirstNibble(int val, int storage)
    {
        return storage |= (val << 4);
    }

    static int StoreSecondNibble(int val, int storage)
    {
        return storage |= val;
    }

    static void WriteBits(int b)
    {
        Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(b),0));
    }
}