位运算符的低级用例是执行以 2 为底的数学运算。有一个众所周知的技巧来测试一个数字是否是 2 的幂:
if ((x & (x - 1)) == 0) {
printf("%d is a power of 2\n", x);
}
但是,它还可以提供更高级别的功能:集合操作。您可以将一组位视为一个集合。解释一下,让一个字节中的每个位代表 8 个不同的项目,比如说我们太阳系中的行星(冥王星不再被认为是行星,所以 8 位就足够了!):
#define Mercury (1 << 0)
#define Venus (1 << 1)
#define Earth (1 << 2)
#define Mars (1 << 3)
#define Jupiter (1 << 4)
#define Saturn (1 << 5)
#define Uranus (1 << 6)
#define Neptune (1 << 7)
然后,我们可以形成一个行星集合(一个子集),比如使用|
:
unsigned char Giants = (Jupiter|Saturn|Uranus|Neptune);
unsigned char Visited = (Venus|Earth|Mars);
unsigned char BeyondTheBelt = (Jupiter|Saturn|Uranus|Neptune);
unsigned char All = (Mercury|Venus|Earth|Mars|Jupiter|Saturn|Uranus|Neptune);
现在,您可以使用 a&
来测试两个集合是否有交集:
if (Visited & Giants) {
puts("we might be giants");
}
该^
操作通常用于查看两个集合之间的不同之处(集合的并减去它们的交集):
if (Giants ^ BeyondTheBelt) {
puts("there are non-giants out there");
}
因此,可以将其|
视为并集、&
交集以及并^
集减去交集。
一旦您接受了位表示集合的想法,那么按位运算自然可以帮助操纵这些集合。