您可能熟悉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
语句中比在条件语句测试中更有意义。)
答案 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)
即使对于这些语句实际上等同的单比特值,我总是赞成显式比较。
它使意图更清晰。我们 对比较标志感兴趣。 (x & Flag) == Flag
是一种既定的模式,我可以在眨眼间处理和识别它。
我通常更喜欢明确的隐式转换。我对失败状态做了例外(例如我写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_REQUIRED
或FLAG_WHICH_IS_REALLY_TWO_FLAGS_COMBINED_WITH_AN_OR
,第一种情况在不应该的情况下返回true。第二种情况正确返回。如果遇到FLAG_WITH_EXACTLY_ONE_BIT_SET的情况,则应使用第二种结构进行编码,以免在标志值更改时产生奇怪的问题。除非您的探查器告诉您挤出所有操作,否则请保持清楚。