为什么__builtin_parity相反



GCC和Clang都支持一个称为__builtin_parity的实现定义函数,该函数有助于确定数字的奇偶性。

根据GCC的规定:

内置函数:int __builtin_parity(unsigned int x)
返回x的奇偶校验,即x中的1位数取2。

这意味着,如果1位的数量是偶数,它将返回0,如果是奇数,则返回1。

Clang也是如此,因为我在编译器资源管理器上进行了测试。

然而,当设置的比特数为偶数时,实际奇偶校验标志被设置。

为什么会这样?

它们只是不同的任意选择。

首先要注意的是;实际奇偶校验标志";是仅在某些架构上提供的硬件功能;在目前主流使用的体系结构中,我认为x86是唯一一个具有这种标志的体系结构。因此,这样一个标志的存在,更不用说确切的语义了,在任何方面都不是一个通用的标准。

我认为GCC的选择更符合逻辑:0和1应该分别对应偶数和奇数,因为0是偶数,1是奇数。我不知道为什么x86和它的前辈们选择了相反的做法。你可能不得不回到过去询问设计师。

无论如何,8086奇偶校验标志的实际值不是很重要;程序员通常会使用JPEJPO汇编助记符来测试它;如果奇偶校验偶数"则跳转";或";如果奇偶校验为奇数则跳转";而不必记住哪一个对应于标志中的0或1位。只有当您想通过PUSHFLAHF实际检查FLAGS寄存器中的位时,该值才会变得相关,这只在非常模糊的情况下有用。

我看了一下历史。英特尔8086从8080复制了其标志,这也起到了同样的作用。它的前身,8008,也有一个平等的";触发器";,它似乎是在偶数奇偶校验上设置的,但有点不清楚,因为你只能有条件地跳到触发器的状态上,而不能实际读取它。据说8008是从Datapoint 2200派生而来的,它实际上以相反的方式记录了它的奇偶校验翻转:设置为奇数,重置为偶数。但是80xx语义可能是一些内部实现细节,没有任何深刻的意义,比如奇偶校验电路恰好以这种方式产生了结果,他们没有费心添加另一个NOT门来反转它

无论如何,x86奇偶校验标志对于GCC的__builtin_parity()来说只是很有用的,因为它只测试一个字节。它可以通过异或将字节放在一起来获得更大的值,如果没有其他选项,GCC/clang会这样做。它通过在最后使用setnp而不是setp来处理标志的反向意义(人类程序员只需编写setpo,而不必考虑标志的设置/清除值)。

然而,过去10年中几乎所有的x86 CPU都支持popcnt指令,如果它可用,GCC/clang将使用它(然后只提取低位)。

最新更新