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;
}

@garmae
Copy link

garmae commented Apr 18, 2021

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