20

Right now I'm using this to set/unset individual bits in a byte:

if (bit4Set)
   nbyte |= (1 << 4);
else
   nbyte &= ~(1 << 4);

But, can't you do that in a more simple/elegant way? Like setting or unsetting the bit in a single operation?

Note: I understand I can just write a function to do that, I'm just wondering if I won't be reinventing the wheel.

djeidot
  • 4,542
  • 4
  • 42
  • 45
  • 4
    http://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit-in-c – obelix Aug 06 '10 at 12:43
  • 4
    @obelix: So this is how SO was before all the trvial questions were answered already? +112/+241, 90 Favs? Great Question/Great Answer Gold Badge? – Nordic Mainframe Aug 06 '10 at 13:09

6 Answers6

15

Sure! It would be more obvious if you expanded the |= and &= in your code, but you can write:

nbyte = (nbyte & ~(1<<4)) | (bit4Set<<4);

Note that bit4Set must be zero or one —not any nonzero value— for this to work.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
12

Put it in a function, the bool type will enforce 0,1 for all bitval inputs.

int change_bit(int val, int num, bool bitval)
{
    return (val & ~(1<<num)) | (bitval << num);
}
Nordic Mainframe
  • 28,058
  • 10
  • 66
  • 83
  • if i put it into a function I'd rather use the code I wrote. It is right, nevertheless. – djeidot Aug 06 '10 at 14:02
  • 5
    If you let the compiler inline this function in C++, then it will be as fast as if you had used the expression itself, plus you get the readability-bonus. – Nordic Mainframe Aug 06 '10 at 14:13
8

This is a perfectly sensible and completely standard idiom.

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
5

Have you considered assigning mnemonics and/or identifiers to your bits, rather than referring to them by number?

As an example, let's say setting bit 4 initiates a nuclear reactor SCRAM. Instead of referring to it as "bit 4" we'll call it INITIATE_SCRAM. Here's how the code for this might look:

int const INITIATE_SCRAM = 0x10; // 1 << 4

...

if (initiateScram) {
    nbyte |= INITIATE_SCRAM;
} else {
    nbyte &= ~INITIATE_SCRAM;
}

This won't necessarily be any more efficient (after optimization) than your original code, but it's a little clearer, I think, and probably more maintainable.

Dan Moulding
  • 211,373
  • 23
  • 97
  • 98
  • that's pretty much the same thing. I'm actually using identifiers, I just didn't put them in the example. – djeidot Aug 06 '10 at 14:04
1
nbyte |= (1 << 4);

If the right hand side of the assignment, (1 << 4), is always a constant like this, then this would probably be optimized by compiler so it will be simpler in resulting assembly:

mov r0, _nbyte
mov r1, 10H         ; here is the optimization, no bit shift occured
or r0, r1
st _nbyte, r0
Donotalo
  • 12,748
  • 25
  • 83
  • 121
  • 4
    This is the answer to the question "How do I set bit 4 in nbyte?". The question is "How do I set or unset bit 4 in nbyte depending on the value of bit4Set?" – Pascal Cuoq Aug 06 '10 at 12:55
  • 1
    Thanks. I misunderstood the question. Should I delete my answer? – Donotalo Aug 07 '10 at 05:09
  • I'd give this answer a thumbs up, because even if it is not entirely on point, it adds additional insight, just as Pascal's did. – TJ Bandrowsky Apr 28 '21 at 01:11
1

This is tagged as C++ so have you considered using std::bitset instead of doing all the bit manipulation yourself? Then you can just use array notation as: bits[3] = bit4Set to set the appropriate bit.

Mark B
  • 95,107
  • 10
  • 109
  • 188