Is there a better way to replace two bits within an 8 bit variable?

Hi,

Variable X holds a two bit value (its an 8 bit length but it can only take values 0,1,2)

I now need to replace the above two bits in a certain (n) position with in the variable outputStatus .

One (ugly) way to achieve this is above is shown below.

Is there a better way to do the same?

if (n==1) {
      outputStatus =(outputStatus & B11111100) | X;
     }
    
 if (n==2) {
      outputStatus=(outputStatus & B11110011) | (X<<2);
   
      }
 if (n==3) {
      outputStatus=(outputStatus & B11001111) | (X<<4);
      
      }

..... 
....

I don't know from better, but different would be to use the bitWrite() function (see the language reference).

You could use bit fields in a struct and pop it in a union:

union BIT_OF_BITS {
  struct {
    uint8_t a : 2; //bits 0..1
    uint8_t b : 2; //bits 2..3
    uint8_t c : 2; //bits 4..5
    uint8_t d : 2; //bits 6..7
  } slices;
  uint8_t packed;
}

BIT_OF_BITS bob;

bob.slices.a = 1;
bob.slices.b = 0;
bob.slices.c = 2;
bob.slices.d = 1;

Serial.print(F("The bits are "));
Serial.println(bob.packed, BIN);

Code is untested but should work.

If instead of using n=1,2,3 use n=0,1,2 it would simplify things
If you can do that, this would work

#define mask0  0xfc
#define mask1  0xf3;
#define mask2  0xcf;

switch (n)

   case 0:   outputStatus &= mask0 ;
                 outputStatus |= (x<<(n*2));

 case 1:   outputStatus &= mask1 ;
                 outputStatus |= (x<<(n*2));

 case 2:   outputStatus &= mask2 ;
                 outputStatus |= (x<<(n*2));

I don't really think there was anything wrong with how were doing it but if we're experimenting with different ways to do this, perhaps pre-compute this limited set of data and use tables:

const byte
    andMask[] =
    {
        0b11111111, //n=0 (not used)
        0b11111100, //n=1
        0b11110011, //n=2
        0b11001111  //n=3    
    };
//X can equal 00, 01, 10 or 11
//n can equal 1, 2 or 3 (0 used as filler; not used)    
const byte
    orMask[4][4] = 
    {
        {
            0b00000000,   //n=0, X=xx not used
            0b00000000,   //n=0, X=xx not used
            0b00000000,   //n=0, X=xx not used
            0b00000000    //n=0, X=xx not used
        },
        {
            0b00000000,   //n=1, X=00
            0b00000001,   //n=1, X=01   
            0b00000010,   //n=1, X=10
            0b00000011    //n=1, X=11
        },
        {
            0b00000000,   //n=2, X=00
            0b00000100,   //n=2, X=01
            0b00001000,   //n=2, X=10
            0b00001100    //n=2, X=11
        },
        {
            0b00000000,   //n=3, X=00
            0b00010000,   //n=3, X=01
            0b00100000,   //n=3, X=10
            0b00110000    //n=3, X=11
        }
    };

int
    n, X;

void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);
    while(!Serial);
    n=0;
    X=0;
    
}

void loop() {
  byte
    outputStatus;
    
  // put your main code here, to run repeatedly:
  for( n=1; n<4; n++ )
  {
    outputStatus = 0;
    for(X=0; X<4; X++)
    {
        outputStatus = (outputStatus & andMask[n]) | (orMask[n][X]);

        Serial.print("n= "); Serial.print(n); Serial.print(" ");
        Serial.print("X= "); Serial.print(X); Serial.print(" ");
        Serial.println(outputStatus,BIN);
        delay(100); 
    }//for
  }//for
}//loop

Thank you all for your contributions.

I was looking for a more code size efficient way to achieve the same thing and was hoping there would be some sort of bit arithmetic manipulation to achieve the same result with out using if (or case) statements.