2

I need to set and clear some bits in bytes of a byte array.

Set works good but clear doesn't compile (I guess because negation has int as result and it's negative by then and ...).

public const byte BIT_1 = 0x01;
public const byte BIT_2 = 0x02;

byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};

// set 1st bit
for (int i = 0; i < bytes.Length; i++)
    bytes[i] |= BIT_1;

// clear 2nd bit (set it to 0)
for (int i = 0; i < bytes.Length; i++)
    bytes[i] &= (~BIT_2);

How can I clear bits in a byte in a preferably simple way ?

Bitterblue
  • 13,162
  • 17
  • 86
  • 124

4 Answers4

12

Try this:

int i = 0;

// Set 5th bit
i |= 1 << 5;

Console.WriteLine(i); // 32

// Clear 5th bit
i &= ~(1 << 5);

Console.WriteLine(i); // 0

Version on bytes (and on bytes only in this case):

byte b = 0;

// Set 5th bit
b |= 1 << 5;

Console.WriteLine(b);

// Clear 5th bit
b &= byte.MaxValue ^ (1 << 5);

Console.WriteLine(b);
Spook
  • 25,318
  • 18
  • 90
  • 167
  • Why not use bitwise not? `~`? What's with the XOR? – Matthew Watson Feb 24 '14 at 10:20
  • 2
    @MatthewWatson `Constant value '-33' cannot be converted to a 'byte'`. XOR is a simple way to remain in positive world, thus allowing to avoid unnecessary casts :) – Spook Feb 24 '14 at 10:53
  • 1
    @Spook But that only works because you have hard-coded the `5` in the shift. Try replacing that with a variable, and it no longer compiles. – Matthew Watson Feb 24 '14 at 11:06
  • @MatthewWatson I haven't checked that. It seems to me then, that the only way is to make a double byte-to-int-to-byte cast... – Spook Feb 24 '14 at 11:43
2

It appears that you can't do this without converting the byte to an int first.

byte ClearBit(byte b, int i)
{
    int x = Convert.ToInt32(b);
    x &= ~(1 << i);
    return Convert.ToByte(x);
}
Bart van Nierop
  • 4,130
  • 2
  • 28
  • 32
1

This can be avoided by converting to an int and back again:

bytes[i] = (byte)(bytes[i] & ~(BIT_2));
Martin
  • 16,093
  • 1
  • 29
  • 48
0

Bitwise operations are not defined on bytes, and using them with bytes will always return an int. So when you use the bitwise NOT on your byte, it will return an int, and as such yield an error when you are trying to AND it with your other byte.

To solve this, you need to explicitely cast the result as a byte again.

byte bit = 0x02;
byte x = 0x0;

// set
x |= bit;
Console.WriteLine(x); // 2

// clear
x &= (byte)~bit;
Console.WriteLine(x); // 0
Community
  • 1
  • 1
poke
  • 369,085
  • 72
  • 557
  • 602
  • This will technically work, but the code (both OP's and yours) is unclear, because it suggests, that if you set `bit` to 0x03 it will clear 3rd bit, but it won't (at least not how OP would want it to). The core problem - as I understand - is to write code which clears n-th bit, not just a specific one. – Spook Feb 24 '14 at 10:07
  • @Spook No, OP’s code does not in any way hint how they would approach the third bit. They could easily set `BIT_3` to `0x04` and everything would be fine. – poke Feb 24 '14 at 10:09