churay
churay

Reputation: 440

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

In order to utilize a byte to its fullest potential, I'm attempting to store two unique values into a byte: one in the first four bits and another in the second four bits. However, I've found that, while this practice allows for optimized memory allocation, it makes changing the individual values stored in the byte difficult.

In my code, I want to change the first set of four bits in a byte while maintaining the value of the second four bits in the same byte. While bitwise operations allow me to easily retrieve and manipulate the first four bit values, I'm finding it difficult to concatenate this new value with the second set of four bits in a byte. The question is, how can I erase the first four bits from a byte (or, more accurately, set them all the zero) and add the new set of 4 bits to replace the four bits that were just erased, thus preserving the last 4 bits in a byte while changing the first four?

Here's an example:

//  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

Upvotes: 10

Views: 18396

Answers (9)

Marcello
Marcello

Reputation: 11

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

Upvotes: 1

Jason Haley
Jason Haley

Reputation: 3800

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

Upvotes: 0

Eric Lippert
Eric Lippert

Reputation: 660503

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.

Upvotes: 12

Igby Largeman
Igby Largeman

Reputation: 16747

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.

Upvotes: 0

Petar Ivanov
Petar Ivanov

Reputation: 93090

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

Upvotes: 0

CodesInChaos
CodesInChaos

Reputation: 108880

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

Upvotes: 2

Ry-
Ry-

Reputation: 225273

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.

Upvotes: 1

Schroedingers Cat
Schroedingers Cat

Reputation: 3139

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;

Upvotes: 0

hammar
hammar

Reputation: 139930

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

Upvotes: 20

Related Questions