I have a status register with 8 bits. I would like to move each individual bit to a byte for further processing. Seems like it should be easy but every solution I come up with is convoluted. I was thinking about iterating through the bits with a for next loop and dumping them into an array but my solution way too messy.
-
[What's the fastest way to pack 32 0/1 values into the bits of a single 32-bit variable?](https://stackoverflow.com/q/26200961/995714), [How to efficiently convert an 8-bit bitmap to array of 0/1 integers with x86 SIMD](https://stackoverflow.com/q/52098873/995714) – phuclv Aug 28 '19 at 02:39
-
It's not an answer to your question, but are you sure you need to do this ? I mean that you could very well use a bit mask every time you need to access a bit, instead of copying each bit in a different variable. Some thing like `if ( status_register & Mask_for_bit_i ) do_something();` will not be more complicated than `if (bits[i]) do_something();` – Guillaume Petitjean Aug 28 '19 at 08:17
3 Answers
Here's basically what you're trying to do. It uses bitwise operators and a uint8_t
array to make each bit an individual byte:
void bits_to_bytes(uint8_t status, uint8_t bits[8])
{
int ctr;
for( ctr = 0; ctr < 8; ctr++ )
{
bits[ctr] = (status >> ctr) & 1;
}
}
OK, so a little more in-depth:
This code loops through the bits in a byte and then assigns bits[bit_number]
to the bit_number
th bit of status
.
If you want to reverse the order the bits are stored in, simply change bits[ctr]
to bits[(8-1)-ctr]
.

- 15,171
- 8
- 38
- 76
For a start, you should be using uint8_t
for eight-bit bit collections since char
is fundamentally non-portable unless you add a lot of extra code for checking its size and signedness.
Something like this should suffice for your needs:
void BitsToBytes(uint8_t bits, uint8_t *bytes) {
for (int i = 0; i < 8; ++i) { // The type has exactly eight bits.
*bytes++ = (bits > 127); // 1 if high bit set, else 0.
bits = (bits & 0x7f) << 1; // Shift left to get next bit.
}
}
:
// Call with:
uint8_t inputBits = 0x42;
uint8_t outputBytes[8];
BitsToBytes(inputBits, outputBytes);
This takes a type with eight bits and a buffer of eight bytes, then places the individual bits into each byte of the array:
MSB LSB
+--------+
inputBits: |abcdefgh|
+--------+
+---+---+---+---+---+---+---+---+
outputBytes: | a | b | c | d | e | f | g | h |
+---+---+---+---+---+---+---+---+
If you want it to go the other way (where the LSB of the input is in element 0 of the array), you can simply change the body of the loop to:
*bytes++ = bits & 1; // 1 if low bit set, else 0.
bits = bits >> 1; // Shift right to get next bit.
-
-
@JL2210: complicated in what way exactly? It does exactly what the question asks for and the calling of the function is relatively simple. – paxdiablo Aug 28 '19 at 00:51
-
But couldn't you just use bit-shifts and `& 1`, like in my solution? – S.S. Anne Aug 28 '19 at 00:52
-
It seems backwards to expectation, the least significant bit is conventionally numbered zero but this places it into `outputBytes[7]`. – caf Aug 28 '19 at 00:53
-
1@JL2210: yes, but I prefer a function based solution so that it doesn't clutter up the code. I also have a natural need for the bytes to echo the bits in a left-to-right sense but that's probably more of a sytle thing :-) – paxdiablo Aug 28 '19 at 00:53
-
-
-
1@caf, have added an addendum for that preference but I still prefer the current way :-) – paxdiablo Aug 28 '19 at 00:59
-
*you should be using `uint8_t` for eight-bit bit collections since `char` is fundamentally non-portable* Given [**7.20.1.1 Exact-width integer types**, paragraph 3](https://port70.net/~nsz/c/c11/n1570.html#7.20.1.1p3). I suspect there's not much *de facto* difference in portability between the two. The most portable would be `uint_least8_t`. – Andrew Henle Aug 28 '19 at 01:24
-
@Andrew, if uint8_t can be represented by an implementation, it must be. The problem with the `least` types is that you have to ensure nothing "leaks" into the bit positions above `b7`, lest checks like `> 127` will not work (in other words, you'll probably need to mask those bits to zero). If you don't *have* `uint8_t` then, yes, `least` is probably better (with a little extra work). Even `unsigned char` is workable with some more effort but I would totally steer clear of `char` just because of its signedness problems. – paxdiablo Aug 28 '19 at 01:48
You can use a double invocation of the !
operator to squash a zero/non-zero value to zero/one. Using this, the extracted value of bit n
in status
is !!(status & (1 << n))
.
If you only have eight flags you might just create constants for the 8 values of 1 << n
(0x1
, 0x2
, 0x4
, 0x8
, 0x10
, 0x20
, 0x40
, 0x80
). This works particularly well if your flags all have individual names rather than numbers, so that you might have in a header file somewhere:
#define FLAG_FROB 0x01
#define FLAG_FOO 0x02
#define FLAG_BAR 0x04
#define FLAG_BAZ 0x08
#define FLAG_QUUX 0x10
Then in the code you'd just extract them as
flag_frob = !!(status & FLAG_FROB);
flag_foo = !!(status & FLAG_FOO);
flag_bar = !!(status & FLAG_BAR);
flag_baz = !!(status & FLAG_BAZ);
flag_quux = !!(status & FLAG_QUUX);

- 233,326
- 40
- 323
- 462
-
Why would you need that when you could use `(status >> n) & 1`? It's simpler, and doesn't use unnecessary screaming. – S.S. Anne Aug 28 '19 at 00:59
-
1@JL2210: Just because the shifted values here are constants rather than using a variable shift. Often you'll have those `(1 << n)` values as defined constants for the various flags anyway since they likely each have their own name. It all depends on whether you're dealing with 8 individually named independent flags or a set of analogous numbered flags (an example of the latter might be 8 free/busy flags for 8 numbered buffers). – caf Aug 28 '19 at 01:07
-