每两个字符反转地址的C程序调试求助:末尾字节无法输出
问题分析与修复方案
嘿,我来帮你捋捋这个问题!你的需求是把0xefba5896这种带0x前缀的十六进制地址字符串,按每两个字符一组反转顺序,最终输出\x96\x58\xba\xef这样的结果,但现在最后一组字节出不来,咱们先看看代码里的问题,再给你修复好。
你的代码里踩的几个坑
字符串复制越界+没加终止符:
你用strncpy(rev, &add[2], strlen(add))的时候,strlen(add)是整个输入的长度(比如0xefba5896长度是10),但rev只开了8个字符的空间,而且&add[2]开始的字符串是8个字符,strncpy复制完不会自动加\0终止符,后面调用strlen(rev)就会读到内存里的垃圾值,循环逻辑直接乱掉。循环条件没覆盖到所有组:
你的循环初始值是strlen(rev)-2,假设rev正常的话初始i是6,然后4、2、0,处理完i=0之后,i-2变成-2,这时候i > -2的条件不满足,循环直接结束——哦不对,你写了if(i==0)处理开头的两个字符,但可能代码没写完,而且这个循环条件确实容易漏掉最后一组(也就是原来的ef)。没处理十六进制到字节的转换:
你复制了两个字符到xa里,但要输出\xXX的格式,得把这两个十六进制字符转换成对应的字节值,再用正确的格式打印出来才行。
修复后的完整代码
下面是能完美实现你需求的代码,每一步我都加了注释:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, char *argv[]) { // 先检查有没有传参数 if (argc != 2) { printf("用法:%s <十六进制字符串>\n", argv[0]); return 1; } char *add = argv[1]; // 校验输入格式:必须以0x开头,且后面的十六进制字符数量是偶数 if (strlen(add) < 3 || add[0] != '0' || add[1] != 'x' || (strlen(add)-2) % 2 != 0) { printf("输入格式不对!应该是类似0xefba5896这样的字符串\n"); return 1; } char *hex_part = &add[2]; // 去掉0x前缀,拿到纯十六进制部分 int hex_len = strlen(hex_part); // 从最后一组两个字符开始,往前遍历每一组 for (int i = hex_len - 2; i >= 0; i -= 2) { char byte_str[3] = {0}; // 存两个十六进制字符+终止符 strncpy(byte_str, &hex_part[i], 2); // 把十六进制字符串转成对应的字节值 unsigned char byte = strtoul(byte_str, NULL, 16); // 输出你要的\xXX格式 printf("\\x%02x", byte); // 如果是要直接输出二进制字节(比如写入文件),就换成下面这句: // printf("%c", byte); } printf("\n"); return 0; }
为啥这样写就行?
- 输入校验:先确保用户传了正确格式的参数,避免非法输入导致程序崩溃。
- 遍历逻辑:从纯十六进制字符串的倒数第二个字符开始,每次往前跳2位,这样从最后一组(
96)一直处理到最开头的一组(ef),所有组都不会漏掉。 - 格式输出:用
strtoul把两个字符的十六进制串转成字节值,再用printf("\\x%02x", byte)输出你想要的\xXX格式,测试输入0xefba5896的话,输出就是\x96\x58\xba\xef,完全符合你的期望。
内容的提问来源于stack exchange,提问作者user9613239
相关产品推荐
相关产品推荐

