我无法理解这段代码。我所知道的是,我们已经将代码传递给汇编程序,汇编程序将代码转换为“字节代码”。现在我有一个虚拟机可以读取这段代码。该函数应该读取第一条字节码指令。我不明白这段代码中发生了什么。我想我们正在尝试阅读这个字节码,但不明白它是如何完成的。
static int32_t bytecode_to_int32(const uint8_t *bytecode, size_t size)
{
int32_t result;
t_bool sign;
int i;
result = 0;
sign = (t_bool)(bytecode[0] & 0x80);
i = 0;
while (size)
{
if (sign)
result += ((bytecode[size - 1] ^ 0xFF) << (i++ * 8));
else
result += bytecode[size - 1] << (i++ * 8);
size--;
}
if (sign)
result = ~(result);
return (result);
}
最佳答案
这段代码写得有些糟糕,一行中有很多操作,因此包含各种潜在的错误。它看起来很脆。
bytecode[0] & 0x80
简单地读取 MSB 符号位,假设它是 2 的补码或类似的,然后将其转换为 bool 值。- 循环从最高有效字节向后迭代到最低有效字节。
- 如果符号为负,代码将执行数据字节与 0xFF 的异或运算。基本上反转数据中的所有位。 XOR 的结果是一个
int
。 - 然后将数据字节(或上述 XOR 的结果)向左移动
i * 8
位。数据始终被隐式提升为int
,因此如果i * 8
恰好给出大于INT_MAX
的结果,则存在大量未定义行为错误在这里。在转换之前转换为uint32_t
,执行转换,然后转换为有符号类型会更安全。 - 生成的
int
被转换为int32_t
- 它们可以是相同类型或不同类型,具体取决于系统。 - i加1,size减1。
- 如果符号为负,则
int32_t
被反转为符号扩展的某个 2 的补码负数,并且所有数据位再次被反转。除了用左移移入的所有零也被一个替换。这是有意还是无意,我说不准。因此,例如,如果您以0x0081
之类的内容开始,您现在拥有类似0xFFFF01FF
的内容。我不知道这种格式有何意义。
我的看法是 bytecode[size - 1] ^ 0xFF
(相当于 ~
)是用来切换数据位的,这样它们以后就会当稍后调用 ~
时切换回它们的原始值。程序员必须用评论记录这些技巧,如果他们接近称职的话。
无论如何,不要使用此代码。如果仅打算交换 4 字节整数的字节顺序(字节顺序),则必须从头开始重写此代码。
正确的做法是:
static int32_t big32_to_little32 (const uint8_t* bytes)
{
uint32_t result = (uint32_t)bytes[0] << 24 |
(uint32_t)bytes[1] << 16 |
(uint32_t)bytes[2] << 8 |
(uint32_t)bytes[3] << 0 ;
return (int32_t)result;
}
任何比上述更复杂的代码都是高度可疑的代码。我们不必担心符号是一种特殊情况,上面的代码保留了原始的符号格式。
关于c - C语言按位运算(0x80、0xFF、<<),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60092227/