【问题标题】:Why would you perform a Bit-shift twice ((x >> 4) << 4)?为什么要执行两次位移 ((x >> 4) << 4)?
【发布时间】:2020-08-31 09:18:52
【问题描述】:

所以我正在分析 Nes-Emulator 代码,我遇到了这行我无法理解的代码:

nMapperID = ((header.mapper2 >> 4) << 4) | (header.mapper1 >> 4);

为什么 header.mapper2 是向右移动一次,然后向左移动一次。

头文件是这个结构体:

struct sHeader
{
    char name[4];
    uint8_t prg_rom_chunks;
    uint8_t chr_rom_chunks;
    uint8_t mapper1;
    uint8_t mapper2;
    uint8_t prg_ram_size;
    uint8_t tv_system1;
    uint8_t tv_system2;
    char unused[5];
} header;

【问题讨论】:

  • 假设你有11110011(11110011 &gt;&gt; 4) &lt;&lt; 4 给你什么?
  • 不是 100% 但会是 11110000 吗?
  • 正确。现在你明白他们为什么这样做了吗?
  • @HamzaKhan 正确。向右移动 N 次,然后向左移动 N 次,有效地将最右边的 N 位设置为 0。在这种情况下,(header.mapper2 &gt;&gt; 4) &lt;&lt; 4header.mapper2 &amp; 0xF0 有效相同
  • char unused[5]; 的意义何在?

标签: c++ emulation bitwise-operators bit-shift


【解决方案1】:

位移是不是位的旋转。出现的新位都是 0。所以这个表达式:

(header.mapper2 >> 4) << 4)

首先清除低4位,然后将所有位移回左侧。

例如如果您有像01010101 这样的位模式,则右移将首先使位成为00000101,然后左移将使其成为01010000(因此清除最右边的4位)。

如果它位的旋转(如您所料),那么它实际上将是一个无操作。

【讨论】:

  • 无论header.mapper2 的大小如何,它都会执行此操作也很有趣。使用掩码这样做,需要将掩码大小与整数大小相匹配,而这种方式几乎与大小无关。
  • @AdrianMole 屏蔽底部 4 位,您需要使用 0xF0 而不是 0x0F。而且你需要使用&amp;而不是&amp;=,因为代码没有修改mapper2,只是读取它
  • @AdrianMole 这并没有更好,我想说它实际上要糟糕得多,因为现代英特尔处理器上的位移性能很糟糕:请参阅youtube.com/watch?v=Rp6_bfZ4nuE
  • 更糟糕,因为它是两个操作的依赖链,其中一个操作(否则将并行运行以在 | 运算符的右侧移动几乎每个处理器)也会这样做。我不确定编译器是否允许将其优化为按位 AND 无论如何。希望那是在一个冷代码部分,所以不管你花 2 个周期还是 15 个周期都没关系。
猜你喜欢
  • 2016-10-07
  • 2016-01-13
  • 2014-11-20
  • 1970-01-01
  • 2019-08-01
  • 1970-01-01
  • 2020-07-18
  • 2018-02-23
相关资源
最近更新 更多