您练习的目的似乎是根据其内存布局将整数转换为字符串,然后再将其转换回来。
否则,您不会试图弄清楚您是否在字节边界上,然后进行位移“体操”。相反,您只需将值左移四位并添加下一个数字,例如:
#include <stdio.h>
#include <string.h>
short dehex (char hexLetter) {
if ((hexLetter >= '0') && (hexLetter <= '9'))
return hexLetter - '0';
return hexLetter - 'A' + 10;
}
int main (void) {
unsigned int o = 0;
char *in = "D2029649";
int len = strlen (in);
for (int i = 0; i < len; i++)
o = (o << 4) + dehex (in[i]);
printf ("%X\n", o);
return 0;
}
你会注意到我已经dehex
稍微改变了函数,因为我不是魔术数字的忠实粉丝,其中字符常量更具可读性(它仍然不能移植到所有实现,例如 EBCDIC,但现在很少有这样的实现)。
该程序将以大写十六进制输出该字符串中的无符号整数值以进行检查:D2029649
。
但是,1234567890
十进制值是十六进制的,499602D2
字节的顺序与字符串中的字节顺序相反。那是因为您使用的是所谓的小端架构。
所以你有两个问题。
首先是您以错误的顺序处理字节以取回原始号码。
您需要从字符串的末尾开始并向后工作,例如:
for (int i = len - 2; i >= 0; i -= 2) ...
第二个是您以错误的顺序执行添加/移位操作。
因为您的原始代码在添加之后移动,所以它到达D2029649
然后向左移动八位,导致02964900
-D2
从左侧移动到遗忘,并且在右侧移动零字节。您需要转移然后添加:
o <<= 8;
o |= ((unsigned char)dehex(in[i]) << 4) + dehex(in[i+1]);
最后,虽然不是必需的,但如果您只使用 unsigned char 返回转换后的 nybble,您可以大大简化您的代码。我将编写的代码如下:
#include <stdio.h>
#include <string.h>
unsigned char dehex (char hexLetter) {
if ((hexLetter >= '0') && (hexLetter <= '9'))
return hexLetter - '0';
return hexLetter - 'A' + 10;
}
int main (void) {
unsigned int num = 1234567890;
char *p = (char*) #
for (int i = 0; i < 4; i++)
printf("%X%X", (*(p+i) & 0xF0) >> 4, *(p+i) & 0x0F);
putchar ('\n');
unsigned int o = 0;
char *in = "D2029649";
int len = strlen (in);
for (int i = len - 2; i >= 0; i -= 2) {
o <<= 8;
o |= (dehex (in[i]) << 4) + dehex (in[i+1]);
}
printf ("%X, or %u\n", o, o);
return 0;
}
请注意,就一次处理一个字节而不是一次处理一个 nybble 而言,这更有意义。使用基于 nybble 的代码,您必须按顺序执行数组索引,6, 7, 4, 5, 2, 3, 0, 1
而不是一个漂亮的0..7
小循环。
这个程序的输出是:
D2029649
499602D2, or 1234567890
表明您正在取回您的原始号码。