Skip to content

Instantly share code, notes, and snippets.

@xsleonard
Created November 6, 2013 18:10
Show Gist options
  • Save xsleonard/7341172 to your computer and use it in GitHub Desktop.
Save xsleonard/7341172 to your computer and use it in GitHub Desktop.
hex string to byte array, C
unsigned char* hexstr_to_char(const char* hexstr)
{
size_t len = strlen(hexstr);
IF_ASSERT(len % 2 != 0)
return NULL;
size_t final_len = len / 2;
unsigned char* chrs = (unsigned char*)malloc((final_len+1) * sizeof(*chrs));
for (size_t i=0, j=0; j<final_len; i+=2, j++)
chrs[j] = (hexstr[i] % 32 + 9) % 25 * 16 + (hexstr[i+1] % 32 + 9) % 25;
chrs[final_len] = '\0';
return chrs;
}
@rrmhearts
Copy link

This is freaking ingenious.

@devendranaga
Copy link

that's nice. how about this one ?

int byteArrayToHexString(uint8_t *byte_array, int byte_array_len,
                         char *hexstr, int hexstr_len)
{
    int off = 0;
    int i;

    for (i = 0; i < byte_array_len; i ++) {
        off += snprintf(hexstr + off, hexstr_len - off,
                           "%02x", byte_array[i]);
    }

    hexstr[off] = '\0';

    return off;
}

@debuti
Copy link

debuti commented Sep 7, 2018

The other way around

char* barray2hexstr (const unsigned char* data, size_t datalen) {
  size_t final_len = datalen * 2;
  char* chrs = (unsigned char *) malloc((final_len + 1) * sizeof(*chrs));
  unsigned int j = 0;
  for(j = 0; j<datalen; j++) {
    chrs[2*j] = (data[j]>>4)+48;
    chrs[2*j+1] = (data[j]&15)+48;
    if (chrs[2*j]>57) chrs[2*j]+=7;
    if (chrs[2*j+1]>57) chrs[2*j+1]+=7;
  }
  chrs[2*j]='\0';
  return chrs;
}

@garcimag
Copy link

It is very nice, but it does not check if the hex string is an actual hex string (for example "3FZP"). Here is a version that does that, also without malloc (since some embedded systems does not implement it (like one I'm currently working with)). Code a little verbose in naming.

int HexStringToBytes(const char *hexStr,
                     unsigned char *output,
                     unsigned int *outputLen) {
  size_t len = strlen(hexStr);
  if (len % 2 != 0) {
    return -1;
  }
  size_t finalLen = len / 2;
  *outputLen = finalLen;
  for (size_t inIdx = 0, outIdx = 0; outIdx < finalLen; inIdx += 2, outIdx++) {
    if ((hexStr[inIdx] - 48) <= 9 && (hexStr[inIdx + 1] - 48) <= 9) {
      goto convert;
    } else {
      if ((hexStr[inIdx] - 65) <= 5 && (hexStr[inIdx + 1] - 65) <= 5) {
        goto convert;
      } else {
        *outputLen = 0;
        return -1;
      }
    }
  convert:
    output[outIdx] =
        (hexStr[inIdx] % 32 + 9) % 25 * 16 + (hexStr[inIdx + 1] % 32 + 9) % 25;
  }
  output[finalLen] = '\0';
  return 0;
}

@rohitsardessai
Copy link

@guigarma This is pretty helpful. When checking if the string is valid hex it only checks for capital letters A-F (ASCII 65 - 70). If you use something like sprintf to produce the hex string then the output will use lowercase letters and the function doesn't work. I added a small check to fix that.

int HexStringToBytes(const char *hexStr,
                     unsigned char *output,
                     unsigned int *outputLen)
{
    size_t len = strlen(hexStr);
    if (len % 2 != 0) {
        return -1;
    }
    size_t finalLen = len / 2;
    *outputLen = finalLen;
    for (size_t inIdx = 0, outIdx = 0; outIdx < finalLen; inIdx += 2, outIdx++) {
        if ((hexStr[inIdx] - 48) <= 9 && (hexStr[inIdx + 1] - 48) <= 9) {
            goto convert;
        } else {
            if (((hexStr[inIdx] - 65) <= 5 && (hexStr[inIdx + 1] - 65) <= 5) || ((hexStr[inIdx] - 97) <= 5 && (hexStr[inIdx + 1] - 97) <= 5)) {
                goto convert;
            } else {
                *outputLen = 0;
                return -1;
            }
        }
    convert:
        output[outIdx] =
            (hexStr[inIdx] % 32 + 9) % 25 * 16 + (hexStr[inIdx + 1] % 32 + 9) % 25;
    }
    output[finalLen] = '\0';
    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment