user1303
user1303

Reputation: 53

Converting array of bits to array of hex in C through bitwise operations

I'm trying to convert an array of bits to an array of bytes, except my operations seem to be reading my bits in the opposite direction from what I want them to be. For example, say the array of binary bits is 10110111 11000000 00000110. I want the byte array to be {B7, C0, 06}. Instead, my code below produces an output of of {ED, 03, 60} i.e. it reads every 8 bits in the opposite direction. Could anyone provide me some suggestions as to where I am going wrong?

void find_hex_arr(uint8_t* bit_arr, int bit_len) {
  uint8_t* hex_arr = malloc(bit_len/8);
  int index = 0;
  unsigned int i = 0;
  unsigned int j = 0;
  for (i = 0; i < bit_len; i = j) {
    for (j = i; j < i + 8; ++j) {
      hex_arr[index] |= bit_arr[j] << (j - i);
    }
    index++;
  }
}

Upvotes: 2

Views: 237

Answers (3)

Mad Physicist
Mad Physicist

Reputation: 114300

Strictly speaking, you don't need two loops, since the two arrays move in lock-step up to a factor of 8.

Your input array is as follows:

uint8_t bit_arr[] = {
    1, 0, 1, 1, 0, 1, 1, 1,
    1, 1, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 1, 1, 0};

The desired output is

uint8_t expected[] = {0xB7, 0xC0, 0x06}

Notice that the most significant bit comes first in this representation. Bits 0-8 in the array are the most to least significant bits in byte 0 of the output and so on.

This plays very well with how basic looping and bit-shifting works. You can push the bits one by one into the least significant bit of the output array:

uint8_t *hex_arr = malloc(bit_len / 8);
memset(hex_arr, 0, bit_len / 8);
for(int i = 0; i < bit_len; i++) {
    hex_arr[i / 8] <<= 1;
    hex_arr[i / 8] += bit_arr[i];
}

The moral of the story is that you must be careful as to how you define your representations and your data. Make sure that you understand where you want things to go conceptually, and you won't have a problem with either graphical or internal representations.

Upvotes: 3

lenik
lenik

Reputation: 23508

You should change this:

for (i = 0; i < bit_len; i = j) {
    for (j = i; j < i + 8; ++j) {
      hex_arr[index] |= bit_arr[j] << (j - i);

into this:

for (i = 0; i < bit_len; i += 8) {
    for (j = 0; j < 8; ++j) {
      hex_arr[index] |= bit_arr[i+j] << (7 - j);

because your shifts reorder bits in the opposite direction.

Upvotes: 0

dbush
dbush

Reputation: 223872

The value that you're shifting is where the problem in.

The first time you enter the inner loop, i is 0 and j is 0. This makes j-i 0 so the value in question gets OR'ed into the rightmost bit instead of the leftmost. Then when j is 1 your shift 1 so the bit goes into the second right bit instead of the second left.

So your shift is going from 0 to 7 when it should be going from 7 to 0. You fix this by subtracting the shift amount from 7.

hex_arr[index] |= bit_arr[j] << (7 - (j - i));

Upvotes: 0

Related Questions