更简单的位运算






4.46/5 (10投票s)
一组简化位运算理解的模板。
引言
我使用 C/C++ 开发软件已经很长时间了,但我仍然需要三思而后行,当我遇到位运算时,更不用说当我必须向其他人解释它们时了!例如
unsigned const STAT_ONE = 0x0001;
unsigned const STAT_TWO = 0x0002;
unsigned status = 0x0001;
if(status & (STAT_ONE | STAT_TWO)) // Does this evaluate to true or false?
DoSomething();
我们都知道前面的语句检查是否同时设置了 STAT_ONE
和 STAT_TWO
位,然后将执行 DoSomething()
... 还是设置了 STAT_ONE
或 STAT_TWO
位? 让我们看看
0001 or // STAT_ONE
0010 // STAT_TWO
----
0011 and // STAT_ONE | STAT_TWO
0001 // status
----
0001 // status & (STAT_ONE | STAT_TWO)
因为结果为非零,所以将执行 DoSomething()
。我认为这可能非常棘手,特别是如果表达式变得太复杂。下面的代码的意图是否更容易理解,并且不易出错?
unsigned const STAT_ONE = 0x0001;
unsigned const STAT_TWO = 0x0002;
unsigned status = 0x0001;
if(isAnyBitSet(status, STAT_ONE | STAT_TWO)) // This evaluates to true, bit
// STAT_ONE is set and bit STAT_TWO
// isn't. Same as previous example
DoSomething();
if(areAllBitsSet(status, STAT_ONE | STAT_TWO)) // This evaluates to false,
// bit STAT_ONE is set but bit
// STAT_TWO isn't
DoSomething();
而且通过其位置访问位的数值也很方便,就像这样
if(isBitSetByPos(status, 5))
bitClearByPos(status, 5);
BitTools.h 头文件中提供的所有函数都是内联的,因此无需担心大小或运行时速度的权衡。
模板
基于位掩码的函数
-
template <class T, class U> bool isAnyBitSet(T value, U mask)
如果
mask
中的任何位在value
中被设置,则返回true
。 定义为:(value & mask) != 0
1010 and // value 0110 // mask ---- 0010 // Non-zero: true
-
template <class T, class U> bool areAllBitsSet(T value, U mask)
如果
mask
中的所有位都在value
中被设置,则返回true
。 定义为:(value & mask) == mask
1010 and // value 1110 // mask ---- 1010 // 1010 == 1010: true
-
template <class T, class U>
bool areAllBitsClear(T value, U mask)
- 如果
mask
中的所有位在value
中被清除,则返回true
。 定义为:(value & mask) == 0
1010 and // value 0101 // mask ---- 0000 // Zero: true
-
template <class T, class U> T setBits(T value, U mask)
将
mask
位设置为value
并返回value
。 定义为:value | mask
1000 or // value 0110 // mask ---- 1110
-
template <class T, class U> T setBitsExcept(T value, U mask)
返回
value
,其中所有位都被设置,除了mask
位。 定义为:value | ~mask
1001 not // mask ---- 0110 or // ~mask 0001 // value ---- 0111
-
template <class T, class U> T clearBits(T value, U mask)
清除
mask
位并返回value
。 定义为:value & ~mask
1001 not // mask ---- 0110 and // ~mask 1111 // value ---- 0110
-
template <class T, class U> T clearBitsExcept(T value, U mask)
返回
value
,其中所有位都被清除,除了mask
位。 定义为:value & mask
0010 and // value 0110 // mask ---- 0010
-
template <class T, class U> T setClearBits(T value, U add, U remove)
返回
value
,其中设置add
位并清除remove
位。 定义为:(value | add) & ~remove
1101 or // value 0101 // add ---- 0111 0001 not // remove ---- 1110 and // ~remove 0111 // value | add ---- 0110
-
template <class T, class U, class V> T setBits(T value, U mask, V set)
根据
set
的值,返回value
,其中设置或清除了mask
位。
基于位置的函数
-
template <class T> T setBitByPos(T value, unsigned char n)
将第
n
位设置为value
并返回value
。 定义为value | (1 << n)
-
template <class T> T clearBitByPos(T value, unsigned char n)
清除第
n
位并返回value
。 定义为value & ~(1 << n)
-
template <class T> bool isBitSetByPos(T value, unsigned char n)
如果
value
具有设置的第n
th 位,则返回true
。 定义为(value & (1 << n)) != 0
-
template <class T> bool isBitClearByPos(T value, unsigned char n)
如果
value
具有清除的第n
th 位,则返回true
。 定义为(value & (1 << n)) == 0
结论
BitTools.h 中包含的模板提供了一种更容易、更不易出错的方式来表达位运算,与手写代码相比,没有性能或大小的损失。 我希望您发现这些函数像我一样有用且易于使用。