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

17,598

Solution 1

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

Solution 2

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.

Solution 3

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

Solution 4

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

Solution 5

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.

Share:
17,598
churay
Author by

churay

Updated on June 05, 2022

Comments

  • churay
    churay almost 2 years

    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
    
  • churay
    churay almost 13 years
    Works like a charm. Thanks a million.
  • CodesInChaos
    CodesInChaos almost 13 years
    this replaces the low four bits, but as I understand it the OP wants to change the high four bits.
  • CodesInChaos
    CodesInChaos almost 13 years
    That only solves half the problem. It erases the high bits, but doesn't replace them.
  • Igby Largeman
    Igby Largeman almost 13 years
    He said "first four" which is ambiguous; personally I interpret it as the lower four as Petar did.
  • Schroedingers Cat
    Schroedingers Cat almost 13 years
    The point is, you can then replace them with something else in the same way.
  • Brian
    Brian almost 13 years
    @minitech: Wikipedia says Nybble is a common alternative spelling.
  • LBushkin
    LBushkin almost 13 years
    Perhaps someday I can convince enough people to consider a two bit integer to be a nyp. :)
  • Jeff LaFay
    Jeff LaFay over 12 years
    @Average Joe, since this worked for you, you need to accept it as the answer to your question.