位运算符让我很难受
本文关键字:很难 运算符 | 更新日期: 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。