我正在试图弄清楚这段代码是如何工作的,但我无法得到一个答案。
#define testbit(x, y) ( ( ((const char*) & (x))[(y)>>3] & 0x80 >> ((y)&0x07)) >> (7-((y)&0x07) ) )
我是新手,所以如果你能找到一种用简体英语解释的方法,我真的很感激。
它属于https://code.google.com/p/xplugins/source/browse/trunk/Xsaitekpanels/SwitchPanel.cpp?r=38行= 19
的X-Plane插件的代码段答案 0 :(得分:7)
宏测试y
中x
位的值。您无法直接寻址位,因此代码首先将x
视为一个字节数组(const char*
强制转换)。
然后查找该位所在的字节。一个字节有8位,所以它除以8.追逐性能,而不是简单地除以8,代码使用右移3位的二进制技巧。通常,对于未签名的x
和y
,x >> y = x/2^y
和x << y = x*2^y
。
此时您需要测试字节内的位,以便获得y/8
的余数。还有一个小技巧,使用y & 7
代替更清晰的y % 8
。
使用此信息,您可以制作一个掩码,一个位,0x80
并将其移位到位以测试y%8
位。掩码与字节进行AND运算,此处的非零结果表示该位设置为1,否则为0.
答案 1 :(得分:2)
完成@ RhythmicFistman的回答
@ RhythmicFistman的答案缺少一小部分,这是轮班的最后一步。
>> (7-((y)&0x07)
步骤确保您只得到1或0的结果。使用此代码可以安全地进行比较,如:
if (testbit(varible, 6) == 1) {
// do something
}
如果没有该步骤testbit
将返回一个位掩码,其中第6位将被设置为1或0,而所有其他位始终设置为0.这是意图,但它没有在什么是便携式方式,请参阅下面的警告3 。
使用此代码的可能问题
现在为其他答案添加一些东西。其他答案没有指出应在此处提及的一些关键字,它们是strict aliasing和shift arithmetic right。我的阐述将以下面的警告形式出现。
警告1:Endianness
此代码假定您使用的是big endian架构,或者只希望从字符数组中获取正确的位。
原因是如果您将int
转换为char
s(字节)数组,您将在big endian计算机与little endian计算机上获得不同的结果
警告2:Strict Aliasing
宏使用了一个转换(const char*) &(x)
,它旨在更改(x)
的类型a.k.a.别名,以便更容易找到正确的位。
这很危险,其原因在this SO answer中得到了很好的解释。简短的版本是,如果你用优化编译这个代码,可能会发生奇怪的事情。
Aliasing和Pointer Aliasing上的维基百科页面也很有用,应该阅读。
除此之外,此代码使用右移位运算符>>
的方式可能存在潜在问题。此运算符有两种不同的行为,具体取决于它所操作的变量是 signed 还是 unsigned 。只要你从不使用负数,你就会安全,但这段代码不能保护你免受这个错误的影响。我怀疑,你不太可能犯这样的错误,所以应该可以使用它。
另外值得一提的是,您正在使用signed char
并正在改变它。虽然这样可行,但我更希望unsigned char
能提高可移植性,因为当char
和int
宽度相同时,它不会产生算术移位的风险(实际上几乎不是这种情况) ,授予)。这是有效的,因为char
升级为int
,请参阅this SO answer以获取解释。
答案 2 :(得分:0)
你看到的是一个宏,它可以完成以下工作:
(按顺序)
因为这个宏非常不合适,而且有点棘手。
位掩码,二进制运算,二进制移位......
如果你能更准确地解释一下你想要了解的内容,也许我可以提供帮助。