if(mask& VALUE)或if((mask& VALUE)== VALUE)?

时间:2011-01-10 16:53:30

标签: c++ bitmask

您可能熟悉enum位掩码方案,例如:

enum Flags {
    FLAG1 = 0x1,
    FLAG2 = 0x2,
    FLAG3 = 0x4,
    FLAG4 = 0x8,

    NO_FLAGS = 0,
    ALL_FLAGS = FLAG1 | FLAG2 | FLAG3 | FLAG4
};

f(FLAG2 | FLAG4);

我已经看过很多代码,然后在掩码中测试某个位,如

if ((mask & FLAG3) == FLAG3)

但这不等于这个吗?

if (mask & FLAG3)

是否有理由使用第一个版本?在我看来,第二个较短的版本更清晰。

也许C程序员的剩余习惯认为真正的价值应该转换为1? (即使在那里,较长的版本在赋值或return语句中比在条件语句测试中更有意义。)

6 个答案:

答案 0 :(得分:79)

构造if ((mask & FLAG3) == FLAG3)测试掩码中是否存在FLAG3中的所有位; if (mask & FLAG3)测试是否存在任何

如果你知道FLAG3只有1位设置,它们是等价的,但是如果你有可能定义复合条件,那么就可以更清楚地养成明确测试所有位的习惯,如果这就是你的意思。

答案 1 :(得分:2)

如果是bitset,那么你只需要比较一个单个位,就可以if(mask & value)

但是,假设您有一个存储在ant int32上的IP地址,并且您想知道它是否为192.168.*,那么您将不得不这样做:

if((ip & 0xFFFF0000) == 0xC0A80000) // assuming some endianness representation.

答案 2 :(得分:2)

即使对于这些语句实际上等同的单比特值,我总是赞成显式比较。

  1. 它使意图更清晰。我们 对比较标志感兴趣。 (x & Flag) == Flag是一种既定的模式,我可以在眨眼间处理和识别它。

  2. 我通常更喜欢明确的隐式转换。我对失败状态做了例外(例如我写if (file)而不是if (file.good()))但是当使用数字时,0不是“失败状态”,它是一个像其他任何数字一样的数字。我不喜欢在布尔上下文中区别对待它。

答案 3 :(得分:1)

if采用布尔值(bool)。前一个表达式直接是bool类型,而后者是一个数值,它将隐式转换为bool

答案 4 :(得分:1)

如果结果非零,则您的条件为真。在您的示例中,两个操作的结果都是等效的,第二个选项甚至可能稍快一些,因为有些CPU可以比其他任意数字更容易测试零,但是:

显然,如果您要检查的值包含多个位,则无法执行第二个选项。在这种情况下,您必须使用第一个选项。如果您同时检查几个位,这显然也适用。

答案 5 :(得分:0)

第一个构造if (mask & FLAG3)的意思是“如果标志和掩码中至少有一个公共位”。例如,如果格式和supported_formats之间的任何位是相同的,则if (formats & supported_formats)将为真。

第二个构造if (mask & FLAG3) == FLAG3表示“如果FLAG3中的所有设置位都在掩码中设置”。例如,如果所有所需的东西都在Things_you_have中,则if (things_you_have & things_required) == things_required将为真。

以下是一些特殊情况的快速提示:

  • 对于FLAG_WITH_EXACTLY_ONE_BIT_SET,这两种情况都有效。
  • 对于OBSOLETE_FLAG_SET_TO_ZERO,第一种情况始终返回false。
  • 对于FLAG_WITH_MULTIPLE_BITS_REQUIREDFLAG_WHICH_IS_REALLY_TWO_FLAGS_COMBINED_WITH_AN_OR,第一种情况在不应该的情况下返回true。第二种情况正确返回。

如果遇到FLAG_WITH_EXACTLY_ONE_BIT_SET的情况,则应使用第二种结构进行编码,以免在标志值更改时产生奇怪的问题。除非您的探查器告诉您挤出所有操作,否则请保持清楚。