C语言hexlify与unhexlify函数转换异常问题求助
分析你的hexlify/unhexlify代码问题
我帮你找出了代码里几个关键问题,正是这些问题导致只有部分十六进制字符能正常转换,其他字符会失败:
1. 缺少必要的头文件
你的代码使用了malloc()、strlen()和system(),但没有包含对应的头文件:
malloc()和system()需要<stdlib.h>strlen()需要<string.h>
缺少头文件会导致函数隐式声明,可能引发未定义行为。
2. a2v()函数未处理大写十六进制字符,分支逻辑有问题
当前a2v()只处理了小写a-f,如果输入是大写A-F,会直接返回0,导致转换错误。另外,原代码的else只绑定第二个if,逻辑不够清晰,还会把非法字符误判为0,建议调整:
int a2v(char c) { if ((c >= '0') && (c <= '9')) { return c - '0'; } if ((c >= 'a') && (c <= 'f')) { return c - 'a' + 10; } if ((c >= 'A') && (c <= 'F')) { // 新增处理大写十六进制的分支 return c - 'A' + 10; } return -1; // 用-1标识非法字符,避免和合法的0混淆 }
3. unhexlify()函数的潜在越界与错误处理缺失
- 没有检查输入字符串长度是否为偶数:如果输入长度是奇数,
i+1会访问超出字符串范围的内存,导致崩溃。 - 没有检查
malloc()返回值:如果内存分配失败,bstr会是NULL,后续操作直接崩溃。 - 循环条件里重复调用
strlen():每次循环都会重新计算字符串长度,影响效率,建议先把长度存起来。
修改后的unhexlify():
char *unhexlify(char *hstr) { if (!hstr) return NULL; size_t hlen = strlen(hstr); // 检查十六进制字符串长度是否为偶数 if (hlen % 2 != 0) { fprintf(stderr, "Error: Hex string length must be even.\n"); return NULL; } size_t blen = hlen / 2; char *bstr = malloc(blen + 1); if (!bstr) { fprintf(stderr, "Error: Memory allocation failed.\n"); return NULL; } char *pbstr = bstr; for (size_t i = 0; i < hlen; i += 2) { int high = a2v(hstr[i]); int low = a2v(hstr[i+1]); // 检查字符是否合法 if (high == -1 || low == -1) { fprintf(stderr, "Error: Invalid hex character at position %zu or %zu.\n", i, i+1); free(bstr); return NULL; } *pbstr++ = (high << 4) | low; // 用位或比加法更安全,逻辑上更准确 } *pbstr = '\0'; return bstr; }
4. hexlify()函数的位操作错误(核心问题)
这是导致大部分转换失败的关键原因:
- 你用了
(bstr[i] >> 4) & 0xFF,但我们只需要取高4位,应该用0x0F。如果char是有符号类型,当字符值大于0x7F时,右移会进行符号扩展,导致结果变成0xFF之类的数值,超出hex数组的索引范围(数组只有16个元素,索引0-15),直接引发数组越界。 - 取低4位时,应该用
bstr[i] & 0x0F,而不是0xFF。
修改后的hexlify():
char *hexlify(char *bstr) { if (!bstr) return NULL; size_t blen = strlen(bstr); char *hstr = malloc(blen * 2 + 1); if (!hstr) { fprintf(stderr, "Error: Memory allocation failed.\n"); return NULL; } char *phstr = hstr; for (size_t i = 0; i < blen; i++) { // 转成unsigned char避免符号扩展问题 unsigned char c = (unsigned char)bstr[i]; *phstr++ = v2a((c >> 4) & 0x0F); // 取高4位 *phstr++ = v2a(c & 0x0F); // 取低4位 } *phstr = '\0'; return hstr; }
5. 其他小问题优化
main()里的input字符串末尾的\0是多余的,字符串字面量会自动添加终止符。- 没有释放
malloc分配的内存,会导致内存泄漏,建议在程序结束前加上释放逻辑。 - 二进制字符串可能包含不可打印字符,直接用
printf("%s")会显示乱码,建议用十六进制逐个字节打印。
完整修改后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int a2v(char c) { if ((c >= '0') && (c <= '9')) { return c - '0'; } if ((c >= 'a') && (c <= 'f')) { return c - 'a' + 10; } if ((c >= 'A') && (c <= 'F')) { return c - 'A' + 10; } return -1; } char v2a(int c) { const char hex[] = "0123456789abcdef"; // 确保索引合法,避免越界 if (c < 0 || c >= 16) { return '?'; } return hex[c]; } char *unhexlify(char *hstr) { if (!hstr) return NULL; size_t hlen = strlen(hstr); if (hlen % 2 != 0) { fprintf(stderr, "Error: Hex string length must be even.\n"); return NULL; } size_t blen = hlen / 2; char *bstr = malloc(blen + 1); if (!bstr) { fprintf(stderr, "Error: Memory allocation failed.\n"); return NULL; } char *pbstr = bstr; for (size_t i = 0; i < hlen; i += 2) { int high = a2v(hstr[i]); int low = a2v(hstr[i+1]); if (high == -1 || low == -1) { fprintf(stderr, "Error: Invalid hex character at position %zu or %zu.\n", i, i+1); free(bstr); return NULL; } *pbstr++ = (high << 4) | low; } *pbstr = '\0'; return bstr; } char *hexlify(char *bstr) { if (!bstr) return NULL; size_t blen = strlen(bstr); char *hstr = malloc(blen * 2 + 1); if (!hstr) { fprintf(stderr, "Error: Memory allocation failed.\n"); return NULL; } char *phstr = hstr; for (size_t i = 0; i < blen; i++) { unsigned char c = (unsigned char)bstr[i]; *phstr++ = v2a((c >> 4) & 0x0F); *phstr++ = v2a(c & 0x0F); } *phstr = '\0'; return hstr; } int main() { char *title = "... Trying to convert hex into binary string and back again ?! ..."; printf("%s\n\n", title); char *input = "0123456789abcdef"; printf("Original: %s (%zu)\n\n", input, strlen(input)); char *input_bin = unhexlify(input); if (!input_bin) { return 1; } printf("Bin: "); // 用十六进制打印每个字节,避免不可打印字符乱码 for (size_t i = 0; i < strlen(input_bin); i++) { printf("%02X ", (unsigned char)input_bin[i]); } printf("(%zu)\n\n", strlen(input_bin)); char *input_hex = hexlify(input_bin); if (!input_hex) { free(input_bin); return 1; } printf("Hex: %s (%zu)\n\n", input_hex, strlen(input_hex)); // 释放内存 free(input_bin); free(input_hex); system("pause"); return 0; }
内容的提问来源于stack exchange,提问作者Kevin Menegatti
相关产品推荐
相关产品推荐

