How do you set, clear, and toggle a single bit?

How do you set, clear, and also toggle a little bit?

2991
2022-06-08 07:48:26
Source Share
Answers: 6

Using the Standard C+npls Library: std::bitset<N>.

Or the Boost variation: boost::dynamic_bitset.

There is no demand to roll your own:

#include <bitset>
#include <iostream>

int main()
{
    std::bitset<5> x;

    x[1] = 1;
    x[2] = 0;
    // Note x[0-4]  valid

    std::cout << x << std::endl;
}

[Alpha:] > ./a.out
00010

The Boost variation permits a runtime sized bitset compared to a standard library compile - time sized bitset.

544
2022-07-01 15:41:22
Source

If you're doing a lot of bit twiddling you might want to use masks which will make the whole thing quicker. The following functions are very fast and are still flexible (they allow bit twiddling in bit maps of any size).

const unsigned char TQuickByteMask[8] =
{
   0x01, 0x02, 0x04, 0x08,
   0x10, 0x20, 0x40, 0x80,
};


/** Set bit in any sized bit mask.
 *
 * @return    none
 *
 * @param     bit    - Bit number.
 * @param     bitmap - Pointer to bitmap.
 */
void TSetBit( short bit, unsigned char *bitmap)
{
    short n, x;

    x = bit / 8;        // Index to byte.
    n = bit % 8;        // Specific bit in byte.

    bitmap[x] |= TQuickByteMask[n];        // Set bit.
}


/** Reset bit in any sized mask.
 *
 * @return  None
 *
 * @param   bit    - Bit number.
 * @param   bitmap - Pointer to bitmap.
 */
void TResetBit( short bit, unsigned char *bitmap)
{
    short n, x;

    x = bit / 8;        // Index to byte.
    n = bit % 8;        // Specific bit in byte.

    bitmap[x] &= (~TQuickByteMask[n]);    // Reset bit.
}


/** Toggle bit in any sized bit mask.
 *
 * @return   none
 *
 * @param   bit    - Bit number.
 * @param   bitmap - Pointer to bitmap.
 */
void TToggleBit( short bit, unsigned char *bitmap)
{
    short n, x;

    x = bit / 8;        // Index to byte.
    n = bit % 8;        // Specific bit in byte.

    bitmap[x] ^= TQuickByteMask[n];        // Toggle bit.
}


/** Checks specified bit.
 *
 * @return  1 if bit set else 0.
 *
 * @param   bit    - Bit number.
 * @param   bitmap - Pointer to bitmap.
 */
short TIsBitSet( short bit, const unsigned char *bitmap)
{
    short n, x;

    x = bit / 8;    // Index to byte.
    n = bit % 8;    // Specific bit in byte.

    // Test bit (logigal AND).
    if (bitmap[x] & TQuickByteMask[n])
        return 1;

    return 0;
}


/** Checks specified bit.
 *
 * @return  1 if bit reset else 0.
 *
 * @param   bit    - Bit number.
 * @param   bitmap - Pointer to bitmap.
 */
short TIsBitReset( short bit, const unsigned char *bitmap)
{
    return TIsBitSet(bit, bitmap) ^ 1;
}


/** Count number of bits set in a bitmap.
 *
 * @return   Number of bits set.
 *
 * @param    bitmap - Pointer to bitmap.
 * @param    size   - Bitmap size (in bits).
 *
 * @note    Not very efficient in terms of execution speed. If you are doing
 *        some computationally intense stuff you may need a more complex
 *        implementation which would be faster (especially for big bitmaps).
 *        See (http://graphics.stanford.edu/~seander/bithacks.html).
 */
int TCountBits( const unsigned char *bitmap, int size)
{
    int i, count = 0;

    for (i=0; i<size; i++)
        if (TIsBitSet(i, bitmap))
            count++;

    return count;
}

Note, to set bit 'n' in a 16 bit integer you do the following:

TSetBit( n, &my_int);

It's up to you to ensure that the bit number is within the range of the bit map that you pass. Note that for little endian processors that bytes, words, dwords, qwords, etc., map correctly to each other in memory (main reason that little endian processors are 'better' than big-endian processors, ah, I feel a flame war coming on...).

20
2022-06-29 23:41:06
Source

From snip-c.zip's bitops.h:

/*
**  Bit set, clear, and test operations
**
**  public domain snippet by Bob Stout
*/

typedef enum {ERROR = -1, FALSE, TRUE} LOGICAL;

#define BOOL(x) (!(!(x)))

#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))

OK, let's analyze things...

The common expression that you seem to be having problems with in all of these is "(1L << (posn))". All this does is create a mask with a single bit on and which will work with any integer type. The "posn" argument specifies the position where you want the bit. If posn==0, then this expression will evaluate to:

0000 0000 0000 0000 0000 0000 0000 0001 binary.

If posn==8, it will evaluate to:

0000 0000 0000 0000 0000 0001 0000 0000 binary.

In other words, it simply creates a field of 0's with a 1 at the specified position. The only tricky part is in the BitClr() macro where we need to set a single 0 bit in a field of 1's. This is accomplished by using the 1's complement of the same expression as denoted by the tilde (~) operator.

Once the mask is created it's applied to the argument just as you suggest, by use of the bitwise and (&), or (|), and xor (^) operators. Since the mask is of type long, the macros will work just as well on char's, short's, int's, or long's.

The bottom line is that this is a general solution to an entire class of problems. It is, of course, possible and even appropriate to rewrite the equivalent of any of these macros with explicit mask values every time you need one, but why do it? Remember, the macro substitution occurs in the preprocessor and so the generated code will reflect the fact that the values are considered constant by the compiler - i.e. it's just as efficient to use the generalized macros as to "reinvent the wheel" every time you need to do bit manipulation.

Unconvinced? Here's some test code - I used Watcom C with full optimization and without using _cdecl so the resulting disassembly would be as clean as possible:

----[ TEST.C ]----------------------------------------------------------------

#define BOOL(x) (!(!(x)))

#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))

int bitmanip(int word)
{
      word = BitSet(word, 2);
      word = BitSet(word, 7);
      word = BitClr(word, 3);
      word = BitFlp(word, 9);
      return word;
}

----[ TEST.OUT (disassembled) ]-----------------------------------------------

Module: C:\BINK\tst.c
Group: 'DGROUP' CONST,CONST2,_DATA,_BSS

Segment: _TEXT  BYTE   00000008 bytes  
 0000  0c 84             bitmanip_       or      al,84H    ; set bits 2 and 7
 0002  80 f4 02                          xor     ah,02H    ; flip bit 9 of EAX (bit 1 of AH)
 0005  24 f7                             and     al,0f7H
 0007  c3                                ret     

No disassembly errors

----[ finis ]-----------------------------------------------------------------

59
2022-06-28 21:51:57
Source

The various other alternative is to make use of little bit areas:

struct bits {
    unsigned int a:1;
    unsigned int b:1;
    unsigned int c:1;
};

struct bits mybits;

specifies a 3 - little bit area (in fact, it is 3 1 - little bit felds). Little bit procedures currently come to be a little bit (haha) less complex:

To set or clear a little bit:

mybits.b = 1;
mybits.c = 0;

To toggle a little bit:

mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1;  /* all work */

Checking a little bit:

if (mybits.c)  //if mybits.c is non zero the next line below will execute

This just collaborates with dealt with - dimension little bit areas. Or else you need to consider the little bit - puddling strategies defined in previous blog posts.

285
2022-06-09 14:04:48
Source

It is occasionally worth making use of an enum to call the little bits:

enum ThingFlags = {
  ThingMask  = 0x0000,
  ThingFlag0 = 1 << 0,
  ThingFlag1 = 1 << 1,
  ThingError = 1 << 8,
}

Then make use of the names later, Ie. write.

thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}

to set, clear and also examination. In this manner you hide the magic numbers from the remainder of your code.

Apart from that I recommend Jeremy is remedy.

135
2022-06-08 16:53:38
Source

Setting a little bit

Use the bitwise OR driver (|) to set a little bit.

number |= 1UL << n;

That will certainly set the nth little number. n needs to be absolutely no, if you intend to set the 1st little bit and more upto n-1, if you intend to set the nth little bit.

Usage 1ULL if number is bigger than unsigned long ; promo of 1UL << n does not take place till after reviewing 1UL << n where it is undefined practices to change by greater than the size of a long. The very same relates to all the remainder of the instances.

Clearing up a little bit

Use the bitwise AND driver (&) to clear a little bit.

number &= ~(1UL << n);

That will certainly clear the nth little number. You have to invert the little bit string with the bitwise NOT driver (~), after that AND it.

Toggling a little bit

The XOR driver (^) can be made use of to toggle a little bit.

number ^= 1UL << n;

That will certainly toggle the nth little number.

Examining a little bit

You really did not request for this, yet I could too add it.

To examine a little bit, change the number n to the right, after that bitwise AND it:

bit = (number >> n) & 1U;

That will certainly place the value of the nth little number right into the variable bit.

Transforming the n th little bit to x

Setting the nth little bit to either 1 or 0 can be attained with the adhering to on a 2 is enhance C+npls execution:

number ^= (-x ^ number) & (1UL << n);

Bit n will certainly be set if x is 1, and also gotten rid of if x is 0. If x has a few other value, you get waste. x = !!x will certainly booleanize it to 0 or 1.

To make this independent of 2 is enhance negation practices (where -1 has actually all little bits set, unlike on a 1 is enhance or sign/magnitude C+npls execution), usage anonymous negation.

number ^= (-(unsigned long)x ^ number) & (1UL << n);

or

unsigned long newbit = !!x;    // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);

It is usually an excellent suggestion to make use of anonymous kinds for mobile bit manipulation.

or

number = (number & ~(1UL << n)) | (x << n);

(number & ~(1UL << n)) will certainly clear the nth little bit and also (x << n) will certainly set the nth little bit to x.

It is additionally usually an excellent suggestion to not to copy/paste code as a whole therefore many individuals make use of preprocessor macros (like the community wiki answer further down) or some type of encapsulation.

4140
2022-06-08 07:59:03
Source