How do I set, clear and toggle a bit in C/C++?
Join them; it only takes a minute:
|
Setting a bitUse the bitwise OR operator (
That will set bit Clearing a bitUse the bitwise AND operator (
That will clear bit Toggling a bitThe XOR operator (
That will toggle bit Checking a bitYou didn't ask for this but I might as well add it. To check a bit, shift the number x to the right, then bitwise AND it:
That will put the value of bit Changing the nth bit to xSetting the
Bit |
|||||||||||||||||||||
|
Using the Standard C++ Library: Or the Boost version: There is no need to roll your own:
The Boost version allows a runtime sized bitset compared with an Standard Library compile-time sized bitset. |
|||||||||||||||||||||
|
The other option is to use bit fields:
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:
To toggle a bit:
Checking a bit:
This only works with fixed-size bit fields. Otherwise you have to resort to the bit-twiddling techniques described in previous posts. |
|||||||||||||||||||||
|
It is sometimes worth using an
Then use the names later on. I.e. write
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. |
|||||||||||||||||||||
|
I use macros defined in a header file to handle bit set and clear:
|
|||||||||||||
|
From snip-c.zip's bitops.how:
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:
If posn==8, it will evaluate to
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 ]----------------------------------------------------------------
----[ TEST.OUT (disassembled) ]----------------------------------------------- Module: C:\BINK\tst.c Group: 'DGROUP' CONST,CONST2,_DATA,_BSS Segment: TEXT BYTE 00000008 bytes No disassembly errors ----[ finis ]----------------------------------------------------------------- |
|||||||||||||
|
For the beginner I would like to explain a bit more with an example: Example:
The
Toggle or Flip:
|
||||
|
Here's my favorite bit arithmetic macro, which works for any type of unsigned integer array from
To set a bit:
To clear a bit:
To toggle a bit:
To test a bit:
etc. |
|||||||||||||
|
Use the bitwise operators: To set last bit in 000b:
To check last bit in foo:
To clear last bit in foo:
I used XXXb for clarity. You'll probably be working with hex representation, depending on the data structure in which you're packing bits. |
|||||
|
As this is tagged "embedded" I'll assume you're using a microcontroller. All of the above suggestions are valid & work (read-modify-write, unions, structs, etc.). However, during a bout of oscilloscope-based debugging I was amazed to find that these methods have a considerable overhead in CPU cycles compared to writing a value directly to the micro's PORTnSET / PORTnCLEAR registers which makes a real difference where there are tight loops / high-frequency ISR's toggling pins. For those unfamiliar: In my example, the micro has a general pin-state register PORTn which reflects the output pins, so doing PORTn |= BIT_TO_SET results in a read-modify-write to that register. However, the PORTnSET / PORTnCLEAR registers take a '1' to mean "please make this bit 1" (SET) or "please make this bit zero" (CLEAR) and a '0' to mean "leave the pin alone". so, you end up with two port addresses depending whether you're setting or clearing the bit (not always convenient) but a much faster reaction and smaller assembled code. |
|||||||||||||||||
|
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.
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. |
|||||||||||||||||
|
More general, for arbitrary sized bitmaps:
|
|||||
|
Check a bit at an arbitrary location in a variable of arbitrary type:
Sample usage:
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. |
|||
|
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).
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...). |
|||||||||||||||||
|
Use this:
|
|||||||||||||
|
This program is to change any data bit from 0 to 1 or 1 to 0:
|
||||
|
Visual C 2010, and perhaps many other compilers, have direct support for bit operations built in. Surprisingly, this works, even the sizeof() operator works properly.
So, to your question, IsGph[i] =1, or IsGph[i] =0 make setting and clearing bools easy. To find unprintable characters...
Note there is nothing "special" about this code. It treats a bit like an integer - which technically, it is. A 1 bit integer that can hold 2 values, and 2 values only. I once used this approach to find duplicate loan records, where loan_number was the ISAM key, using the 6-digit loan number as an index into the bit array. Savagely fast, and after 8 months, proved that the mainframe system we were getting the data from was in fact malfunctioning. The simplicity of bit arrays makes confidence in their correctness very high - vs a searching approach for example. |
|||||||||||||||||||||
|
Use one of the operators as defined here. To set a bit, used |
|||||
|
Expanding on the
|
|||
|
Here are some macros I use:
|
|||
|
If you want to perform this all operation with c programming in linux kernel then i suggest to use standard apis of linux kernel. See https://www.kernel.org/doc/htmldocs/kernel-api/ch02s03.html
Note: Here whole operation happens in a single step, So these all are guaranteed to be atomic even on SMP computers and are useful to keep coherence across processors. |
|||
|
Try one of these functions in C language to change n bit
Or
Or
|
|||||||||
|
protected by Praveen Sep 12 '14 at 11:57
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?