unsigned char to unsigned char array of 8 original bits

2.5k views Asked by At

I am trying to take a given unsigned char and store the 8 bit value in an unsigned char array of size 8 (1 bit per array index).

So given the unsigned char A

Id like to create an unsigned char array containing 0 1 0 0 0 0 0 1 (one number per index)

What would be the most effective way to achieve this? Happy Thanksgiving btw!!

3

There are 3 answers

0
amaurea On BEST ANSWER

The fastest (not sure if that's what you menat by "effective") way of doing this is probably something like

void char2bits1(unsigned char c, unsigned char * bits) {
    int i;
    for(i=sizeof(unsigned char)*8; i; c>>=1) bits[--i] = c&1;
}

The function takes the char to convert as the first argument and fills the array bits with the corresponding bit pattern. It runs in 2.6 ns on my laptop. It assumes 8-bit bytes, but not how many bytes long a char is, and does not require the input array to be zero-initialized beforehand.

I didn't expect this to be the fastest approach. My first attempt looked like this:

void char2bits2(unsigned char c, unsigned char * bits) {
    for(;c;++bits,c>>=1) *bits = c&1;
}

I thought this would be faster by avoiding array lookups, by looping in the natural order (at the cost of producing the bits in the opposite order of what was requested), and by stopping as soon as c is zero (so the bits array would need to be zero-initialized before calling the function). But to my surprise, this version had a running time of 5.2 ns, double that of the version above.

Investigating the corresponding assembly revealed that the difference was loop unrolling, which was being performed in the former case but not the latter. So this is an illustration of how modern compilers and modern CPUs often have surprising performance characteristics.

Edit: If you actually want the unsigned chars in the result to be the chars '0' and '1', use this modified version:

void char2bits3(unsigned char c, unsigned char * bits) {
    int i;
    for(i=sizeof(unsigned char)*8; i; c>>=1) bits[--i] = '0'+(c&1);
}
6
NetVipeC On

You could use bit operators as recommended.

#include <stdio.h>

main() {
    unsigned char input_data = 8;
    unsigned char array[8] = {0};
    int idx = sizeof(array) - 1;
    while (input_data > 0) {
        array[idx--] = input_data & 1;
        input_data /= 2; // or input_data >>= 1;
    }

    for (unsigned long i = 0; i < sizeof(array); i++) {
        printf("%d, ", array[i]);
    }
}
0
Chris On

Take the value, right shift it and mask it to keep only the lower bit. Add the value of the lower bit to the character '0' so that you get either '0' or '1' and write it into the array:

unsigned char val = 65;
unsigned char valArr[8+1] = {};

for (int loop=0; loop<8; loop++)
    valArr[7-loop] = '0' + ((val>>loop)&1);

printf ("val = %s", valArr);