The classic problem of testing and setting individual bits in an integer in C is perhaps one the most common intermediate-level programming skills. You set and test with simple bitmasks such as
unsigned int mask = 1<<11; if (value & mask) {....} // Test for the bit value |= mask; // set the bit value &= ~mask; // clear the bit
An interesting blog post argues that this is error prone, difficult to maintain, and poor practice. The C language itself provides bit level access which is typesafe and portable:
typedef unsigned int boolean_t; #define FALSE 0 #define TRUE !FALSE typedef union { struct { boolean_t user:1; boolean_t zero:1; boolean_t force:1; int :28; /* unused */ boolean_t compat:1; /* bit 31 */ }; int raw; } flags_t; int create_object(flags_t flags) { boolean_t is_compat = flags.compat; if (is_compat) flags.force = FALSE; if (flags.force) { [...] } [...] }
But this makes me cringe.
The interesting argument my coworker and I had about this is still unresolved. Both styles work, and I maintain the classic bitmask method is easy, safe, and clear. My coworker agrees it's common and easy, but the bitfield union method is worth the extra few lines to make it portable and safer.
Is there any more arguments for either side? In particular is there some possible failure, perhaps with endianness, that the bitmask method may miss but where the structure method is safe?
Bit Fields in C Language In programming terminology, a bit field is a data structure that allows the programmer to allocate memory to structures and unions in bits in order to utilize computer memory in an efficient manner.
Bit fields can be used to reduce memory consumption when a program requires a number of integer variables which always will have low values. For example, in many systems storing an integer value requires two bytes (16-bits) of memory; sometimes the values to be stored actually need only one or two bits.
Binary AND Operator copies a bit to the result if it exists in both operands. Binary OR Operator copies a bit if it exists in either operand. Binary XOR Operator copies the bit if it is set in one operand but not both.
This is a C Program to implement Bit Array. A bit array is an array data structure that compactly stores bits. It can be used to implement a simple set data structure. A bit array is effective at exploiting bit-level parallelism in hardware to perform operations quickly.
Bitfields are not quite as portable as you think, as "C gives no guarantee of the ordering of fields within machine words" (The C book)
Ignoring that, used correctly, either method is safe. Both methods also allow symbolic access to integral variables. You can argue that the bitfield method is easier to write, but it also means more code to review.
If the issue is that setting and clearing bits is error prone, then the right thing to do is to write functions or macros to make sure you do it right.
// off the top of my head #define SET_BIT(val, bitIndex) val |= (1 << bitIndex) #define CLEAR_BIT(val, bitIndex) val &= ~(1 << bitIndex) #define TOGGLE_BIT(val, bitIndex) val ^= (1 << bitIndex) #define BIT_IS_SET(val, bitIndex) (val & (1 << bitIndex))
Which makes your code readable if you don't mind that val has to be an lvalue except for BIT_IS_SET. If that doesn't make you happy, then you take out assignment, parenthesize it and use it as val = SET_BIT(val, someIndex); which will be equivalent.
Really, the answer is to consider decoupling the what you want from how you want to do it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With