使用掩蔽的原因

时间:2010-12-20 16:01:13

标签: c

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)

非常感谢任何建议,

3 个答案:

答案 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_MASKIPEV_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操作来定义常量(而不是简单地编写十六进制文字)的原因是为了提高可读性。无论如何编译器会将它们优化为固定值,运行时不会有任何位计算。但是这种写作风格让你一眼就能理解哪个常数包含其他常量。当然,如果您要修改其中一个,那么更改将自动反映在适当的位置。

这是否更清晰?如果您还有其他问题,请随时提出!