位运算符让我很难受

本文关键字:很难 运算符 | 更新日期: 2023-09-27 18:18:35

我正试图将我的思想围绕xbox 360的STFS文件结构,我正在阅读的页面给出了这个代码示例,用于查找代码块的偏移量:

internal int BlockToOffset(int xBlock)
{
    int xReturn = 0;
    if (xBlock > 0xFFFFFF)
        xReturn = -1;
    else
        xReturn = (((MetaData.HeaderSize + 0xFFF) & 0xF000) + (xBlock << 12));
    return xReturn;
}

xBlock将是您试图查找偏移量的块号。我不确定标题大小的意义是什么,但我认为它决定了其余代码的多少被抵消。不管怎样,我搞不懂位运算符在做什么。头大小为38682,块0位于0xA000,但是,我也不知道这是如何工作的。

有人能帮我一下吗?

edit:任何关于使用位操作符的信息都很棒。我知道它们是如何工作的,但我就是不明白它们是如何被使用的,尤其是在这种情况下,这似乎在提高它们的效率。

位运算符让我很难受

让我们从末尾开始拆分:

xBlock << 12

这个左移运算符告诉我们块大小是4096,因为:

1 << 12 = 1000000000000 (binary) = 4096 (decimal)

现在,第一部分是给标题大小添加一个常量:

MetaData.HeaderSize + 0xFFF

0xFFF是4095。请注意,它只比4096小1。

1000000000000 (4096 in binary)
0111111111111 (4095 in binary)

下一部分现在清除较低的12位,因为二进制中的0xF000是:

1111000000000000 (1111 followed by 12 0s)

那么,据我所知,发生的事情是:

1)取头大小并添加块大小- 1

2)清除低12位,这是舍入到块大小的下一个最接近的倍数。我不是100%确定这部分,但我尝试了一些例子(001 + 111)&1000 vs (111 + 111) &

3)当前值是块0的偏移量开始的地方,所以加上4096的适当倍数来获得块的偏移量

让我们来分析一下:

(MetaData.HeaderSize + 0xFFF) & 0xF000

这部分本质上是"找到0x1000的下一个最高倍数",类似于"天花板"函数。
例如,如果HeaderSize从0x0001到0x1000,它将四舍五入到0x1000。但是如果是从0x1001到0x2000,它将四舍五入到0x2000,等等。

(xBlock << 12)

这与xBlock * 0x1000相同,因为2^12 = 0x1000 = 4096。

因此,为了找到您的偏移量,您取标题,找到下一个最高的倍数0x1000,并为每个块添加0x1000。