Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitfield manipulation in C

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?

like image 732
SPWorley Avatar asked Jun 25 '09 15:06

SPWorley


People also ask

What is Bitfield in C programming?

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.

What is the use of Bitfield?

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.

How do Bitwise operators work in C?

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.

Can you execute bit array in C language?

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.


2 Answers

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.

like image 95
Matthew Flaschen Avatar answered Oct 18 '22 07:10

Matthew Flaschen


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.

like image 27
plinth Avatar answered Oct 18 '22 09:10

plinth