C# Language: Changing the First Four Bits in a Byte

▼魔方 西西 提交于 2019-12-03 12:40:20

Use bitwise AND (&) to clear out the old bits, shift the new bits to the correct position and bitwise OR (|) them together:

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

Here's what happens:

                       value        : abcdefgh
                       newFirstFour : 0000xyzw

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

When I have to do bit-twiddling like this, I make a readonly struct to do it for me. A four-bit integer is called nybble, of course:

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

And then add implicit conversions between TwoNybbles and byte. Now you can just treat any byte as having a High and Low byte without putting all that ugly bit twiddling in your mainline code.

You first mask out you the high four bytes using value & 0xF. Then you shift the new bits to the high four bits using newFirstFour << 4 and finally you combine them together using binary or.

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

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

I'm not really sure what your method there is supposed to do, but here are some methods for you:

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

Should be self-explanatory.

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

Example:

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

  • 135 = 10000111

  • 9 = 1001
  • 9 << Pos = 100100
  • Result = 10100111

A quick look would indicate that a bitwise and can be achieved using the & operator. So to remove the first four bytes you should be able to do:

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

return value1&value2;

Assuming newVal contains the value you want to store in origVal. Do this for the 4 least significant bits:

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

and this for the 4 most significant bits:

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

I know you asked specifically about clearing out the first four bits, which has been answered several times, but I wanted to point out that if you have two values <= decimal 15, you can combine them into 8 bits simply with this:

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

The result will be xxxxyyyy where

xxxx = upperFour
yyyy = lowerFour

And that is what you seem to be trying to do.

Here's some code, but I think the earlier answers will do it for you. This is just to show some sort of test code to copy and past into a simple console project (the WriteBits method by be of help):

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));
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!