gcc 4.4.1 c89
我正在使用我们之前的程序员制作的API。但是,我有点困惑为什么他们为什么要掩盖这个原因。
使用蒙版OR
十六进制的原因是什么?将IPEV_ERROR_MASK与IPEV_START进行OR运算的原因是什么。为什么不只有十六进制值?
#define IPEV_MASK 0x9000
#define IPEV_ERROR_MASK (IPEV_MASK | 0x0800)
#define IPEV_OPEN (IPEV_MASK | 0x01)
#define IPEV_START (IPEV_MASK | 0x02)
#define IPEV_MEDIA_FAIL (IPEV_ERROR_MASK | IPEV_START)
非常感谢任何建议,
答案 0 :(得分:3)
它看起来像分类(或分组)方法。似乎所有"IPEV"
值都包含0x9000。后续值当然可以定义为一个简单的十六进制值,但给定的方法有点自我记录,有助于避免在添加新值时出错。
一种可能的用法是,一段代码可以检查值的IPEV_MASK部分,以查看“代码”是否属于该组。
if (( someCode & IPEV_MASK ) == IPEV_MASK )
// do something
答案 1 :(得分:1)
Masks可帮助您从整数中提取所需的位,并丢弃您不感兴趣的位。
值0x9000
在二进制文件中如下所示:
1001 0000 0000 0000
所以这个掩码的意图是使用第12和第15位,丢弃其余部分。
IPEV_ERROR_MASK
是IPEV_MASK
中设置的位加上0000 1000 0000 0000
中设置的位的组合。所以可能是第11位被保留用于指示是否发生了错误,并且将其与IPEV_START
中的IPEV_MEDIA_FAIL
组合是有意义的。
答案 2 :(得分:1)
不确定哪一部分不清楚,所以我会解释一切。
首先,它们显然是有点旗帜。位标志是一种在单个数字中存储大量布尔值的方法。例如,典型的32位整数可以存储32个布尔值。这具有双重优点,即在存储器中非常紧凑,并且能够容易地一次传递多个值。当然,缺点是要访问单个值,您必须使用按位运算符。因此,在处理代码中的布尔值时通常不使用此方法,但通常在存储值或传递它们时使用。另请注意,虽然您可以将每个可用的布尔值混合在一起,但通常只使用此技巧将相关值组合在一起(例如对象的状态标志或其他内容)。
现在,使用位标志有几种传统。例如,您始终使用每个位的描述性名称定义常量。否则它真的很快就会变得很尴尬。 (嗯......现在17号的意思是......)
另一方面,即使您理论上可以使用|
运算符,也始终使用+
运算符将多个标志连接在一起。这又有两个原因:一个原因是|
比+
快,但更重要的是,如果你不小心包含相同的标志两次,{{1运算符将提供正确的答案,而|
会使所有内容变得混乱。
这是一个真正的危险,因为在比特标志的世界中,通常不仅要看每个比特的常数,还要看常见组合的常数。使用+
运算符,您可以加入这些运算符,并确保结果将包含您想要的位,而不必担心是否可能将相同的位设置为两次。
因此,我们来看你的例子:
|
显然我们在某处有某种“IPEV”位掩码字段,这些是其位的命名常量。第一个常量是#define IPEV_MASK 0x9000
#define IPEV_ERROR_MASK (IPEV_MASK | 0x0800)
#define IPEV_OPEN (IPEV_MASK | 0x01)
#define IPEV_START (IPEV_MASK | 0x02)
#define IPEV_MEDIA_FAIL (IPEV_ERROR_MASK | IPEV_START)
,它设置位号15和12.然后是常量IPEV_MASK
,其中包括IPEV_MASK,另外还设置位11.依此类推。依此类推。 / p>
他们使用这些IPEV_ERROR_MASK
操作来定义常量(而不是简单地编写十六进制文字)的原因是为了提高可读性。无论如何编译器会将它们优化为固定值,运行时不会有任何位计算。但是这种写作风格让你一眼就能理解哪个常数包含其他常量。当然,如果您要修改其中一个,那么更改将自动反映在适当的位置。
这是否更清晰?如果您还有其他问题,请随时提出!