c - C语言按位运算(0x80、0xFF、<<)

标签 c bit-manipulation core bitwise-and bitwise-or

我无法理解这段代码。我所知道的是,我们已经将代码传递给汇编程序,汇编程序将代码转换为“字节代码”。现在我有一个虚拟机可以读取这段代码。该函数应该读取第一条字节码指令。我不明白这段代码中发生了什么。我想我们正在尝试阅读这个字节码,但不明白它是如何完成的。

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/

相关文章:

asp.net-core - 在容器的核心控制台应用程序中获取ASPNETCORE_ENVIRONMENT

c - 帕斯卡和 C : different output

c - 不确定为什么程序不终止

c - 二维数组是双指针吗?

c - 分配动态多个数组

python - 字符串的按位运算Python3.7

java - 这个按位运算符的实现有何意义?

javascript - 算法题 Decode Hex to set output

linux - 如何制作删除文件的shell脚本

java - Solr异常: Error opening new searcher