【发布时间】:2021-11-22 13:06:40
【问题描述】:
我有一些 C 代码。在其中,我有一个无符号长整数形式的 64 位值。我想将其转换为 2 个不同的 32 位值。如何安全地做到这一点?这是我的第一次尝试:
char buff[16];
unsigned long int long_number;
unsigned int long_number_hi32;
unsigned int long_number_lw32;
long_number = 0x0123456789ABCDEFul;
long_number_hi32 = (unsigned int)(long_number >> 32);
long_number_lw32 = (unsigned int)(long_number >> 0);
kwrite("0x");
// This is a custom itoa function with params:
// (number (32-bit integer), buffer_ptr, buffer_length, base, pad_to_min_length)
itoa(long_number_hi32, buff, 16, 16, 8);
kwrite(buff);
itoa(long_number_lw32, buff, 16, 16, 8);
kwrite(buff);
kwrite("\n");
但是我得到的输出是:
0x01234567FFFFFFFF89ABCDE
检查组件,发现问题:
LUI a0,0x01234
ADDI a0,a0,1383
# ...
# Call itoa
# Call kwrite
LUI a0,0x89abd
ADDI a0,a0,-529
# ...
# Call itoa
# Call kwrite
在 64 位 RISC-V 汇编中,LUI 符号扩展提供的 20 位立即数,将目标寄存器的高 32 位设置为立即数的第 20 位。因此,寄存器 a0 以 0xFFFFFFFF89ABCDEF 结尾。我希望我的结果在 'E' 处被截断,以防止我的缓冲区溢出,方法是将 NULL 终止符放在我的 'F' 本来的位置。
我要补充一点,我的代码看起来与我提供的示例不完全相同,因为我已将 uint32_t、uint64_t、int32_t 和 int64_t 类型定义为 unsigned int、unsigned long int、signed int 和signed long int 类型的构建分别。我只是用内置类型代替了示例。
这应该如何在 C 中完成以确保可移植性正确?我必须使用工会吗?除了工会还有其他安全的方法吗?
【问题讨论】:
-
你的
itoa函数是做什么的?我怀疑它是为使用 signed 整数而设计的。 -
... 在无符号整数不是的情况下,有符号整数往往会进行符号扩展
-
我觉得自己很笨。你们是对的。我以为我已经对 itoa 函数进行了编码,如果给定一个基数,则将其视为无符号数!= 10。但是我在一年前编写了这个 itoa 函数并忘记了它实际上是以提供基数为负数的条件甚至不是一个完成的功能。我只是在查看它的源代码。很抱歉浪费了您的时间。
-
@EchelonX-Ray 没问题!这样的事情会发生。
-
如果我将输入参数更改为无符号整数,它会按预期工作。