如何在C中正确地将hex字符串转换为字节数组?

我需要将包含hex值的字符串转换为字节数组。 虽然这已经在这里作为第一个答案回答了,但我收到以下错误:

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

因为我不喜欢警告,而且遗漏hh只会产生另一个警告

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

我的问题是:如何做到这一点? 为了完成,我再次在这里发布示例代码:

 #include  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); } 

您可以使用strtol()代替。

只需更换此行:

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

有:

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

更新 :您可以避免使用此代码段使用sprintf()

 char buf[5] = {"0", "x", pos[0], pos[1], 0}; val[count] = strtol(buf, NULL, 0); 

您可以将编译器切换到C99模式( hh长度修饰符在C99中标准化),或者您可以使用unsigned int临时变量:

 unsigned int byteval; if (sscanf(pos, "%2x", &byteval) != 1) { /* format error */ } val[count] = byteval; 

如果不使用sscanf,strol等,为什么不这样做。下面是HexToBin和免费蜜蜂BinToHex。 (注意最初通过错误记录系统返回枚举错误代码而不是简单的-1返回。)

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

使用mvp的建议更改,我创建了此函数,其中包括错误检查(无效字符和不均匀长度)。

此函数将转换hex字符串 – 不以“0x”为前缀 – 使用偶数个字符转换为指定的字节数。 如果遇到无效字符,或者hex字符串的长度为奇数,则返回-1,成功时返回0。

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