繁体   English   中英

基于8个十六进制字节创建了一个无符号的int

[英]Created an unsigned int based on 8 hexadecimal bytes

我试图将unsigned int打印为十六进制,而不是简单地使用%08X 我需要先用MSB打印每个字节的MSB和LSB的十六进制。 我得到了:

unsigned int num = 1234567890;
char *p = (char*)#
for (int i = 0; i < 4; i++) {
    printf("%X%X", (*(p+i) & 0xF0) >> 4, *(p+i) & 0x0F);
}
// prints: D2029649

但是我很难从包含D2029649的字符串返回到unsigned int

short dehex(char hexLetter) {
  if(hexLetter > 47 && hexLetter < 58) hexLetter -= 48;
  if(hexLetter > 64) hexLetter -= 55;
  return hexLetter;  
}

unsigned int o = 0;
char *in = "D2029649";
int len = strlen(in);
for(int i = 0; i < len; i++) {
    if(i % 2 == 0) {
        o |= ((unsigned char)dehex(in[i]) << 4) + dehex(in[i+1]);
        o <<= 8;
    }
}

不用说,这根本不起作用。 操纵o的两行代码是我尝试撤消原始编码所做的结果以及我对如何将字节变回int所做的一些研究的结果。

也许我的麻烦来自对生成十六进制时我实际上在做什么的完全误解。

有没有人有什么技巧可以使我朝正确的方向前进,以使十六进制返回到原始的unsigned int?

练习的目的似乎是根据其内存布局将整数转换为字符串,然后再将其转换回字符串。

否则,您将不会费劲尝试找出自己是否在字节边界上,然后进行移位“体操”。 相反,您只需将值左移四位并添加下一位,例如:

#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函数,因为我不是魔术数字的dehexdehex数字中,字符常量更具可读性(它仍然不能移植到所有实现中,例如EBCDIC,但是周围很少有这样的实现)如今)。

该程序将以大写十六进制形式从该字符串输出无符号整数值以进行检查: D2029649

但是,十进制值1234567890以十六进制表示为499602D2 ,其字节顺序与字符串中的字节顺序相反。 那是因为您使用的是所谓的小端架构。

所以你有两个问题。

首先是您以错误的顺序处理了字节,以取回原始编号。

您需要从字符串的末尾开始并向后工作,例如:

for (int i = len - 2; i >= 0; i -= 2) ...

第二个原因是您以错误的顺序执行添加/移位操作。

因为您的原始代码加法之后发生了移位,所以到达D2029649 ,然后将其左移8位,从而产生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*) &num;
    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的代码,您将必须按6、7、4、5、2、3、0、1的顺序进行数组索引6, 7, 4, 5, 2, 3, 0, 1而不是一个不错的0..7循环。

该程序的输出为:

D2029649
499602D2, or 1234567890

显示您正在找回原始号码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM