How to convert Hex string to byte array in C?

I need to convert a string containing hexadecimal values ​​as characters to an array of bytes. Although this answer has already been answered here , I get the following error:

warning: ISO C90 does not support the 'hh' gnu_scanf length modifier [-Wformat] 

Since I don't like warnings, and omitting hh just creates another warning

 warning: format '%x' expects argument of type 'unsigned int *', but argument 3 has type 'unsigned char *' [-Wformat] 

My question is: how to do it right? To complete, I will send an example code again:

 #include <stdio.h> int main(int argc, char **argv) { const char hexstring[] = "deadbeef10203040b00b1e50", *pos = hexstring; unsigned char val[12]; size_t count = 0; /* WARNING: no sanitization or error-checking whatsoever */ for(count = 0; count < sizeof(val)/sizeof(val[0]); count++) { sscanf(pos, "%2hhx", &val[count]); pos += 2 * sizeof(char); } printf("0x"); for(count = 0; count < sizeof(val)/sizeof(val[0]); count++) printf("%02x", val[count]); printf("\n"); return(0); } 
+4
c arrays type-conversion
Aug 16 '13 at 7:14
source share
4 answers

You can use strtol() instead.

Just replace this line:

 sscanf(pos, "%2hhx", &val[count]); 

from:

 char buf[10]; sprintf(buf, "0x%c%c", pos[0], pos[1]); val[count] = strtol(buf, NULL, 0); 

UPDATE Use sprintf() instead with this snippet:

 char buf[5] = {"0", "x", pos[0], pos[1], 0}; val[count] = strtol(buf, NULL, 0); 
+2
Aug 16 '13 at 7:22
source share
— -

You can switch your compiler to C99 mode (the hh length modifier was standardized to C99), or you can use the temporary variable unsigned int :

 unsigned int byteval; if (sscanf(pos, "%2x", &byteval) != 1) { /* format error */ } val[count] = byteval; 
+2
Aug 16 '13 at 7:31 on
source share

Using the proposed mvp change, I created this function that includes error checking (invalid characters and uneven length).

This function converts a hexadecimal string - NOT added with "0x" - with an even number of characters to the number of bytes specified. It will return -1 if it encounters an invalid character, or if the hexadecimal string has an odd length and 0 if successful.

 //convert hexstring to len bytes of data //returns 0 on success, -1 on error //data is a buffer of at least len bytes //hexstring is upper or lower case hexadecimal, NOT prepended with "0x" int hex2data(unsigned char *data, const unsigned char *hexstring, unsigned int len) { unsigned const char *pos = hexstring; char *endptr; size_t count = 0; if ((hexstring[0] == '\0') || (strlen(hexstring) % 2)) { //hexstring contains no data //or hexstring has an odd length return -1; } for(count = 0; count < len; count++) { char buf[5] = {'0', 'x', pos[0], pos[1], 0}; data[count] = strtol(buf, &endptr, 0); pos += 2 * sizeof(char); if (endptr[0] != '\0') { //non-hexadecimal character encountered return -1; } } return 0; } 
0
Feb 02 '14 at 13:11
source share

Why not do it without using sscanf, strol, etc. Below is HexToBin and how the free Bee BinToHex. (Note. Enumeration error codes were initially returned through the error logging system, rather than a simple -1 return.)

 unsigned char HexChar (char c) { if ('0' <= c && c <= '9') return (unsigned char)(c - '0'); if ('A' <= c && c <= 'F') return (unsigned char)(c - 'A' + 10); if ('a' <= c && c <= 'f') return (unsigned char)(c - 'a' + 10); return 0xFF; } int HexToBin (const char* s, unsigned char * buff, int length) { int result; if (!s || !buff || length <= 0) return -1; for (result = 0; *s; ++result) { unsigned char msn = HexChar(*s++); if (msn == 0xFF) return -1; unsigned char lsn = HexChar(*s++); if (lsn == 0xFF) return -1; unsigned char bin = (msn << 4) + lsn; if (length-- <= 0) return -1; *buff++ = bin; } return result; } void BinToHex (const unsigned char * buff, int length, char * output, int outLength) { char binHex[] = "0123456789ABCDEF"; if (!output || outLength < 4) return; *output = '\0'; if (!buff || length <= 0 || outLength <= 2 * length) { memcpy(output, "ERR", 4); return; } for (; length > 0; --length, outLength -= 2) { unsigned char byte = *buff++; *output++ = binHex[(byte >> 4) & 0x0F]; *output++ = binHex[byte & 0x0F]; } if (outLength-- <= 0) return; *output++ = '\0'; } 
0
Jan 25 '17 at 1:12
source share



All Articles