解释位测试宏在c++

Explain Bit Test macro in C++

本文关键字:c++ 测试 解释      更新时间:2023-10-16

我想弄清楚这段代码是如何工作的,但是我不能得到一个单一的答案。

#define testbit(x, y)  ( ( ((const char*) & (x))[(y)>>3] & 0x80 >> ((y)&0x07)) >> (7-((y)&0x07) ) )

我是新手,所以如果你能想出一个方法用简单的英语解释这个,我将非常感激。

它属于一段代码的X-Plane插件找到https://code.google.com/p/xplugins/source/browse/trunk/Xsaitekpanels/SwitchPanel.cpp?r=38 line=19

宏测试xy -th位的值。您不能直接寻址位,因此代码首先将x视为字节数组(const char*强制转换)。

然后查找该位所在的字节。一个字节有8位,所以要除以8。为了追求性能,代码不是简单地除以8,而是使用二进制技巧,右移3位。一般来说,对于无符号xy, x >> y = x/2^yx << y = x*2^y

此时,您需要测试字节内的位,这样您就可以得到y/8的余数。还有一个小技巧,使用y & 7而不是更清晰的y % 8

有了这些信息,你可以制作一个掩码,一个单开位,0x80,并将其移位到y%8 -th位测试的位置。掩码对字节进行并和,这里的非零结果表示该位被设置为1,否则为0。

完成@RhythmicFistman的答案

@RhythmicFistman的答案缺少了一小部分,那就是转变的最后一步。

>> (7-((y)&0x07)步骤确保您只获得1或0的结果。使用这段代码,可以安全地进行如下比较:

if (testbit(varible, 6) == 1) {
    // do something
}

如果没有该步骤,testbit将返回一个位掩码,其中第6位将被设置为1或0,而所有其他位始终被设置为0。这就是目的,但它不是以可移植的方式实现的,参见下面的警告3

使用此代码可能出现的问题

现在给其他答案添加一些东西。其他答案没有指出一些应该在这里提到的关键字,它们是严格混叠右移算术。我将在下面以警告的形式加以阐述。

警告1:字节顺序

此代码假设您正在使用大端结构,或者仅希望从字符数组中获得正确的位。

原因是如果你把一个int转换成一个char s(字节)的数组,你会在一个大的端序机器和一个小的端序机器上得到不同的结果。

警告2:严格的混叠

宏使用了一个强制转换(const char*) &(x),它被设计用来改变(x)的类型,也就是别名,以便更容易得到正确的位。

这是危险的,原因在这个SO答案中得到了很好的解释。简而言之,如果你用优化编译这段代码,可能会发生奇怪的事情。

关于混叠和指针混叠的维基百科页面也很有用,应该阅读。

警告3:Shift Arithmetic Right

除此之外,这段代码使用右移操作符>>的方式可能存在潜在的问题。该操作符有两种不同的行为,这取决于它操作的变量是有符号还是无符号。只要你不使用负数,你将是安全的,但这个代码不会保护你免受这个错误。不过,我怀疑你不太可能犯这样的错误,所以使用它应该是可以的。

同样值得一提的是,您正在使用signed char并将其右移。虽然这可以工作,但我更喜欢unsigned char,它可以提高可移植性,因为当charint的宽度相同时,它不会冒产生算术移位的风险(这在实践中几乎从来没有发生过)。这是有效的,因为char被提升为int的移位,参见这个SO答案的解释。

您看到的是一个宏,它执行以下任务:

(为了)

  • 进行位移位到y (value: 3)
  • 取x的地址并选择y位置的字符(到字符串x中)
  • 在所选字符和0x80之间进行二进制操作
  • 向前一个结果(值:y和0x7之间二进制运算的结果)做位移位
  • 在前一个结果(值:7 - (y和0x7之间的二进制运算结果))上做位移位

嗯,这对你有帮助吗?我不这么认为!

因为这个宏显然是不合适的,而且有点棘手。

位掩码,二进制操作,二进制移位…

如果你能更准确地解释一下你想要理解的内容,也许我能有所帮助。