C语言 不使用sprintf将无符号整数转换为十六进制字符串

pn9klfpd  于 2023-03-07  发布在  其他
关注(0)|答案(3)|浏览(158)

我正在尝试实现以下代码(没有sprintf或格式化):

void integer_to_string(unsigned int a, char *string)
{
    char arr[16] = "0123456789abcdef";
    char *p = (char *)&a;
    unsigned int i;

    for (i = 0; i < 4; i++) {
        unsigned char lo = p[i] & 0xf; 
        unsigned char hi = p[i] >> 4;

        string[i * 2] = arr[hi];
        string[i * 2 + 1] = arr[lo];
    }
    string[2 * i] = '\0';
}

这个程序将整数a转换成十六进制,剩下的保存为字符串,所以,它应该返回一个int,比如10"0000000a",但是却给了我一个值"0a000000",我做错了什么?,我怎么把0a移到末尾而不是开头呢?

dfddblmv

dfddblmv1#

通过char *p = (char *)&a;访问正确的有效字节取决于字节序,在OP的情况下,顺序错误。
使用数学运算而不是类型转换来获得正确的顺序并避免字节序问题:

for (i = 0; i < 8; i++) {
    unsigned char ch = (a >> ((32-4) - i*4)) & 0xF; 
    string[i] = arr[ch];
}
string[i] = '\0';

存在简化。

4c8rllxm

4c8rllxm2#

也许不是最好的,但肯定是一个快速的...
此函数返回一个char*,该char* 包含传递给它的任何32位或更少的无符号整数的十六进制版本...
例如...... U32甲苯己烷(284598256);将返回字符 * 中的“0x 10 F69 FF 0”
返回char[]必须在函数外声明,因为返回局部变量的指针将不起作用!

char dex[11] = "0x00000000";

const char* u32tohex(uint32_t ul)
{
 const char HexC[17]="0123456789ABCDEF";
 for (uint8_t xh=9; xh>1; xh--)
  {dex[xh]=HexC[ul&0xf]; ul>>=4;}
 return &dex;
}

或不带前缀“0x”的相同字符串...例如... u32 tohex(121345243);将返回char* 中的“073 B 94 DB”

char dex[9] = "00000000";

const char* u32tohex(uint32_t ul)
{
 const char HexC[17]="0123456789ABCDEF";
 for (uint8_t xh=0; xh<8; xh++) 
  {dex[7-xh]=HexC[ul&0xf]; ul>>=4;}
 return &dex;
}

乍一看可能有点难以理解,但对变量的操作越少,总是会产生一个快速的函数...传递给函数的32位无符号整数存储在ul中,循环从char[] result的末尾开始,然后向后循环...因为我只对ul与0xf进行了位AND运算,以获得最低有效半字节,在一个镜头和设置最后的字符形式的HexC[]...和右移的ul的4位,摆脱最后一个半字节,并取代它的下一个...只有8次迭代,工作就完成了...它可能似乎没有用有一个快速的功能为此目的,为几个公约,但是如果你在反汇编程序中使用它,在屏幕上的每一行显示地址,以及来自这些地址的数据,刷新的速度,而滚动屏幕将非常响应,与许多其他解决方案相比...

at0kjp5o

at0kjp5o3#

输出不正确,因为您的系统对内存中构成int值的字节使用little endian排序。这是当今非常常见的情况。将a的地址转换为char *会导致代码不可移植。
相反,您应该以这种方式编写不依赖于整数内部表示形式的可移植代码:

// convert an unsigned int to its hexadecimal representation in a string
// assuming str points to an array of at least 9 bytes
// assuming unsigned int type has 32 bits
// returns its second argument for ease of use in chained expressions
char *integer_to_string(unsigned int a, char *str) {
    str[8] = '\0';
    for (int i = 0; i < 8; i++) {
        str[7 - i] = "0123456789abcdef"[a & 0xF];
        a = a >> 4;
    }
    return str;
}

相关问题