views:

31976

answers:

15

How to set, clear and toggle a bit in C?

+1  A: 

Use the bitwise operators: & |

to set last bit in 000b :

foo = foo | 001b

to check last bit in foo:

if ( foo & 001b ) ....

to clear last bit in foo:

foo = foo & 110b

I used XXXb for clarity. You'll probably be working with hex representation, depending on the data structure in which you're packing bits.

nsanders
+254  A: 

Setting a bit

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

 number |= 1 << x;

That will set bit x.

Clearing a bit

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

 number &= ~(1 << x);

That will clear bit x. You must invert the bit string with the bitwise NOT operator (~), then AND it.

Toggling a bit

The XOR operator (^) can be used to toggle a bit.

 number ^= 1 << x;

That will toggle bit x.

Checking a bit

You didn't ask for this but I might as well add it.

To check a bit, AND it with the bit you want to check:

 bit = number & (1 << x);

That will put the value of bit x into the variable bit.

yjerem
I would like to note that on platforms that have native support for bit set/clear (ex, AVR microcontrollers), compilers will often translate 'myByte |= (1 << x)' into the native bit set/clear instructions whenever x is a constant, ex: (1 << 5), or const unsigned x = 5.
Aaron
1010 reputation points on one answer....
orlandu63
Naww. Because of the limit of 200 a day it is only 895
Martin York
bit = number will not put the value of bit x into bit unless bit has type _Bool (<stdbool.h>). Otherwise, bit = !!(number will..
Chris Young
These sorts of solutions only work when the target variable is of an integral type. More general solutions can be made to work on other useful target types, such as arrays.
John Zwinck
(I've added an answer of my own which includes an implementation of bit-test taking into account what I just mentioned.)
John Zwinck
"Ooo Ah Just a little bit..."
Svish
+14  A: 

It is sometimes worth using an enum to name the bits:

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

Then use the names later on. I.e. write

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

to set, clear and test. This way you hide the magic numbers from the rest of your code.

Other than that I endorse Jeremy's solution.

dmckee
+47  A: 

The other option is to use bit fields:

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

struct bits mybits;

defines a 3-bit field (actually, it's three 1-bit felds). Bit operations now become a bit (haha) simpler:

To set or clear a bit:

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

To toggle a bit:

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

Checking a bit:

if (mybits.c)

This only works with bits in fixed positions. Otherwise you have to resort to the bit-twiddling techniques described in previous posts.

Ferruccio
I'm a sucker for puns, what can I say?
Andrew Hedges
ah, what's that :1 initialization called..
bobobobo
bit field member declarator?
David Thornley
R..
+6  A: 

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

/*
**  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 in all of these that you seem to be having problems with 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 0002 80 f4 02 xor ah,02H 0005 24 f7 and al,0f7H 0007 c3 ret

No disassembly errors

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

yogeesh
2 things about this: (1) in perusing your macros, some may incorrectly believe that the macros actually set/clear/flip bits in the arg, however there is no assignment; (2) your test.c is not complete; I suspect if you ran more cases you'd find a problem (reader exercise)
Dan
A: 

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 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...).

Tim Ring
Don't use a table for a function that can be implemented with a single operator. TQuickByteMask[n] is equivalent to (1<<n).Also, making your arguments short is a very bad idea. The / and % will actually be a division, not bitshift/bitwise and, because signed division by a power of 2 cannot be implemented bitwise. You should make the argument type unsigned int!
R..
+52  A: 

Nobody mention the STL std::bitset
Or the boost version boost::dynamic_bitset

No need 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

Boost version allows a runtime sized bitset compared with STL compile time sized bitset.

Martin York
+1. Not that std::bitset is usable from "C", but as the author tagged his/her question with "C++", AFAIK, your answer is the best around here... std::vector<bool> is another way, if one knows its pros and its cons
paercebal
Nice one, Martin! You can even use an enum to 'index' the bits: enum { cEngineOn, cDoorsOpen, cAircoOn };std::bitset< cNBBITS > mybits;mybits[ cEngineOn ].set();const bool cbDoorOpen = mybits[ cDoorsOpen ];...
xtofl
among the answers here, i think this is the best way to manage bits...but I guess the spirit of the question was how to manipulate bits manually. still, +vote :)
moogs
@paercebal: vector<bool> isn't very efficient, as bool in C++ takes up a full byte of space, instead of 1 bit…
andrewdotnich
@andrewdotnich: vector<bool> is (unfortunately) a specialization that stores the values as bits. See http://www.gotw.ca/publications/mill09.htm for more info...
Niklas
+5  A: 

read this: http://graphics.stanford.edu/~seander/bithacks.html

and, when you'll master this, read this one: http://realtimecollisiondetection.net/blog/?p=78

ugasoft
+3  A: 

I use macros defined in a header file to handle bit set and clear:

/* a=target variable, b=bit number to act upon 0-n */
#define BIT_SET(a,b) ((a) |= (1<<(b)))
#define BIT_CLEAR(a,b) ((a) &= ~(1<<(b)))
#define BIT_FLIP(a,b) ((a) ^= (1<<(b)))
#define BIT_CHECK(a,b) ((a) & (1<<(b)))

/* x=target variable, y=mask */
#define BITMASK_SET(x,y) ((x) |= (y))
#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
#define BITMASK_FLIP(x,y) ((x) ^= (y))
#define BITMASK_CHECK(x,y) ((x) & (y))
Steve Karg
+1  A: 

The bitfield approach has other advantages in the embedded arena. You can define a struct that maps directly onto the bits in a particular hardware register.

struct HwRegister {
    unsigned int errorFlag:1;  // one-bit flag field
    unsigned int Mode:3;       // three-bit mode field
    unsigned int StatusCode:4;  // four-bit status code
};

struct HwRegister CR3342_AReg;

You need to be aware of the bit packing order - I think it's MSB first, but this may be implementation-dependent. Also, verify how your compiler handlers fields crossing byte boundaries.

You can then read, write, test the individual values as before.

Roddy
+1  A: 

Check a bit at an arbitrary location in a variable of arbitrary type:

#define bit_test(x, y)  ( ( ((const char*)&(x))[(y)>>3] & 0x80 >> ((y)&0x07)) >> (7-((y)&0x07) ) )

Sample usage:

int main(void)
{
    unsigned char arr[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };

    for (int ix = 0; ix < 64; ++ix)
        printf("bit %d is %d\n", ix, bit_test(arr, ix));

    return 0;
}

Notes: This is designed to be fast (given its flexibility) and non-branchy. It results in efficient SPARC machine code when compiled Sun Studio 8; I've also tested it using MSVC++ 2008 on amd64. It's possible to make similar macros for setting and clearing bits. The key difference of this solution compared with many others here is that it works for any location in pretty much any type of variable.

John Zwinck
+3  A: 

You may also be interested in checking out The Bit Twiddler, Bit Twiddling Hacks, and The Aggregate Magic Algorithms.

Anthony Cuozzo
+1  A: 

how about this

int ToggleNthBit ( unsigned char n, int num ) {

if(num & (1 << n)) num &= ~(1 << n); else num |= (1 << n);

return num; }

+2  A: 

More general, for arbitrary sized bitmaps:

#define BITS 8
#define BIT_SET(  p, n) (p[(n)/BITS] |=  (0x80>>((n)%BITS)))
#define BIT_CLEAR(p, n) (p[(n)/BITS] &= ~(0x80>>((n)%BITS)))
#define BIT_ISSET(p, n) (p[(n)/BITS] &   (0x80>>((n)%BITS)))
bill
+1  A: 

Here's my favorite bit arithmetic macro, which works for any type of unsigned integer array from unsigned char up to size_t (which is the biggest type that should be efficient to work with):

#define BITOP(a,b,op) \
 ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))

To set a bit:

BITOP(array, bit, |=);

To clear a bit:

BITOP(array, bit, &=~);

To toggle a bit:

BITOP(array, bit, ^=);

To test a bit:

if (BITOP(array, bit, &)) ...

etc.

R..
It's good to read but one should be aware of possible side effects. Using `BITOP(array, bit++, |=);` in a loop will most likely not do what the caller wants.
mxp
Indeed. =) One variant you might prefer is to separate it into 2 macros, 1 for addressing the array element and the other for shifting the bit into place, ala `BITCELL(a,b) |= BITMASK(a,b);` (both take `a` as an argument to determine the size, but the latter would never evaluate `a` since it appears only in `sizeof`).
R..