Home > Back-end >  How to convert Hex to binary in C and output binary as a char array?
How to convert Hex to binary in C and output binary as a char array?

Time:07-08

I'm trying to write a function that converts hex char into binary array so it's easy to read all the ones and zeros one by one. Am having problems with the code. I currently have written the code below. It gives me an error saying that it returns an address of a local variable, even though I tried to make it return a char.

char *hex_to_bin(const char input[]) {
    char output[] = "";
    int i = 0;
    while (input[i]) {
        switch (input[i]) {
          case '0':
            strcat(output, "0000");
            break;
          case '1':
            strcat(output, "0001");
            break;
          case '2':
            strcat(output, "0010");
            break;
          case '3':
            strcat(output, "0011");
            break;
          case '4':
            strcat(output, "0100");
            break;
          case '5':
            strcat(output, "0101");
            break;
          case '6':
            strcat(output, "0110");
            break;
          case '7':
            strcat(output, "0111");
            break;
          case '8':
            strcat(output, "1000");
            break;
          case '9':
            strcat(output, "1001");
            break;
          case 'A':
            strcat(output, "1010");
            break;
          case 'B':
            strcat(output, "1011");
            break;
          case 'C':
            strcat(output, "1100");
            break;
          case 'D':
            strcat(output, "1101");
            break;
          case 'E':
            strcat(output, "1110");
            break;
          case 'F':
            strcat(output, "1111");
            break;
          case 'a':
            strcat(output, "1010");
            break;
          case 'b':
            strcat(output, "1011");
            break;
          case 'c':
            strcat(output, "1100");
            break;
          case 'd':
            strcat(output, "1101");
            break;
          case 'e':
            strcat(output, "1110");
            break;
          case 'f':
            strcat(output, "1111");
            break;
        }
        i  ;
    }
    return output;
}

Perhaps this is a silly approach, but I only recently picked up C.

CodePudding user response:

There are 2 major problems in your code:

  • char output[] = ""; defines an array of char just large enough to hold the empty string. For you purpose, you should allocate an array with a size 4 * strlen(input) 1
  • return output; returns the address of a local object, which will become invalid as soon as the function returns. You could instead allocate memory from the heap with malloc() and return the pointer. The caller will be responsible for freeing this object.

Here is a modified version:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *hex_to_bin(const char input[]) {
    char *output = malloc(strlen(input) * 4   1);
    if (output != NULL) {
        char *p = output;
        int i = 0;
        *p = '\0';
        while (input[i]) {
            switch (input[i]) {
              case '0':
                strcpy(p, "0000");
                break;
              case '1':
                strcpy(p, "0001");
                break;
              case '2':
                strcpy(p, "0010");
                break;
              case '3':
                strcpy(p, "0011");
                break;
              case '4':
                strcpy(p, "0100");
                break;
              case '5':
                strcpy(p, "0101");
                break;
              case '6':
                strcpy(p, "0110");
                break;
              case '7':
                strcpy(p, "0111");
                break;
              case '8':
                strcpy(p, "1000");
                break;
              case '9':
                strcpy(p, "1001");
                break;
              case 'A':
              case 'a':
                strcpy(p, "1010");
                break;
              case 'B':
              case 'b':
                strcpy(p, "1011");
                break;
              case 'C':
              case 'c':
                strcpy(p, "1100");
                break;
              case 'D':
              case 'd':
                strcpy(p, "1101");
                break;
              case 'E':
              case 'e':
                strcpy(p, "1110");
                break;
              case 'F':
              case 'f':
                strcpy(p, "1111");
                break;
              default:
                p[0] = input[i];
                p[1] = '\0';
                break;
            }
            i  ;
            p  = strlen(p);
        }
    }
    return output;
}

int main() {
    char *p = hex_to_bin("n = DeadBeef\n");
    printf("%s\n", p);
    free(p);
    return 0;
}

CodePudding user response:

Code fails as it attempts to return an undersized local array. output[] is too small and local arrays are invalid once the function ends.

Instead, consider passing in a destination array.

// Return NULL on error
char *hex_to_bin(size_t size, char *dest, const char input[]) {
  // Enough room? 
  size_t len = strlen(input);
  if (dest == NULL || len * 4   1 < size) {
    return NULL;
  }

  char *s = dest;
  size_t i;
  // Iterate until a non-hex digit found ....
  for (i = 0; isxdigit((unsigned char) dest[i]); i  ) {
    // Rather than a huge switch table, how about scanning a string of length 1?
    unsigned digit;
    sscanf((char[2]){ dest[i], '\0'}, "%x", &digit);
    // Now convert to binary 
    for (unsigned mask = 8; mask; mask >>= 1) {
      *s   = mark & digit ? '1' : '0';
    }
  }
  *s = '\0';
  if (dest[i] != '\0') { // Was a non-hex digit found?
    return NULL; 
  }
  return dest;
}                      
  • Related