我正在尝试实现以下(没有
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
转换并将a
转换为十六进制并将其余部分保存为字符串。因此,它应该将 10
之类的 int 返回给 "0000000a"
,但它却给我一个 "0a000000"
的值。我究竟做错了什么?如何将0a
移动到结尾而不是开头。
通过
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';
存在简化。
也许不是最好的,但肯定是快的......
此函数返回一个 char* 内容,其中包含传递给它的任何 32 位或更少的无符号整数的 HEX 版本...
例如... u32tohex(284598256);将在 char*
中返回“0x10F69FF0”return 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'的相同... 例如... u32tohex(121345243);将在 char*
中返回“073B94DB”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[] 结果的结果,然后倒退...因为我只对 0xf 按位与 ul,以获得最低有效的半字节,一次性设置最终字符形成 HexC[]... 并右移ul 的 4 位,去掉最后一个半字节,并用下一个半字节替换它……只有 8 次迭代,工作就完成了……为此目的,有一个快速函数似乎没有用,因为一些约定,但是如果你在反汇编器中使用它,显示屏幕上每一行的地址,以及来自这些地址的数据,刷新的速度,同时滚动屏幕将非常敏感,与许多其他解决方案...
输出不正确,因为您的系统对构成内存中
int
值的字节使用小端排序。这是当今非常普遍的情况。将 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;
}