“嗨,阿米戈!”

“我还想谈谈位掩码和 XOR。”

“您已经知道数字由位组成,您可以对这些位执行各种操作。位掩码表示几个不同的逻辑值(真/假值)作为单个整数。在这种情况下,每个布尔值对应于一个特定的位。这是如何做到的:“

“二(1、2、4、8、16、32,...)的幂的二进制表示只涉及设置一位:”

数字 二进制表示
1个 0000 0001
2个 0000 0010
4个 0000 0100
8个 0000 1000
16 0001 0000
19(不是二的幂) 0001 0011
31(不是二的幂) 0001 1111

“因此,任何整数都可以被视为位数组或布尔值数组。”

“以下是如何在一个数字中存储不同的布尔值:”

布尔值
boolean a = true;
boolean b = false;
boolean c = true;
boolean d = false;
值打包成一个数字:
int result = 0;
 if (a) result += 1; // 1 == 20 — bit 0
 if (b) result += 2; // 2 == 21 — bit 1
 if (c) result += 4; // 4 == 22 — bit 2
 if (d) result += 8; // 8 == 23 — bit 3

“现在,如果相应的布尔变量为真,则每一位都为 1。”

在我们的例子中,变量 a 和 c 为真,所以结果等于 1+4 == 5

0000 0101
0000 dcba

“我想我知道发生了什么。”

“好吧,既然你明白了,那我们就继续吧。”

“一个int有32位。其中一位用于数字的符号,另外31位可用于存储31个布尔变量的值。”

“一个 long 有 64 位,我们可以在其中存储 63 个布尔变量。”

“是的。”

“一个数字里塞满了几十个变数,真是不少啊。”

“但这适用于什么地方?”

“主要是在你需要存储大量关于对象的信息的情况下。当你存储关于一个对象的大量信息时,总会有几十个布尔变量。“通过这种方法,它们都可以方便地存储在一个数字中”

“重点在‘存’字上。因为实际使用这个号码并不是那么方便。”

“对了,这正是我想问的。我们如何从数字中提取布尔值?”

“一点都不复杂。假设你需要确定第 6 位是否设置为 1(2 的 5 次方是 32)。我们可以这样检查:”

将数字合并为一个:
int a = 32; // 25 == 0010 0000
int b = 8; // 23 == 0000 1000
int c = 2; // 21 == 0000 0010

int result = a + b + c; // 32 + 8 + 2 == 42 == 0010 1010
通过检查特定位来提取值:
int a = result & 32; // 0010 1010 & 0010 0000 = 0010 0000
int b = result & 8; // 0010 1010 & 0000 1000 = 0000 1000
int c = result & 2; // 0010 1010 & 0000 0010 = 0000 0010

“因此,使用位掩码涉及三个操作:”

1) 将特定位设置为0

2) 将特定位设置为1

3) 检查特定位的值。

“以第 6 位为例。”

“如何将位 6 设置为 1?”

代码 描述
result = result | 01000000;
result |= 01000000;
如何将第 6 位设置为 1?
result = result & 10111111;
result &= 10111111;
如何将第 6 位设置为 0?
c = result & 01000000;
你如何获得第 6 位的值?

“这很不寻常,但并不难。伙计,现在我是一个热门程序员。”

“还有一个关于如何轻松获取特定位设置为 0 或 1 的数字的小提示:01000000 或 10111111。”

为此,我们有 >>和 <<运算符。

“1 是 2 的零次方。换句话说,第 0 位设置为 1 的数字。我们需要第 6 位设置的数字。”

int c = 1 << 6; // 0000 0001 << 6 == 0100 0000 == 64

“太棒了!这对这种情况真的很有帮助。”

“但是,如果我需要一个数字,其中除了一个特定位设置为 0 之外,每个位都设置为 1 怎么办?”

“那也不难:”

int d = ~(1 << 6); // ~0100 0000 == 10111111

“也就是说,一切都很简单:”

代码 描述
result = result | (1 << 6);
result |= (1 << 6);
如何将第 6 位设置为 1?
result = result & ~(1 << 6);
result &= ~(1 << 6);
如何将第 6 位设置为 0?
c = result & (1 << 6);
你如何获得第 6 位的值?

“看起来并不难。但我不会马上记住它。”

“但是,如果你在别人的代码中遇到像“result &= ~(1 << 6)”这样可怕的表达式,你就会知道这个人只是在使用位掩码。”

“如果你经常遇到它,它就会为你记住自己。”

“记住自己……听起来不错。谢谢你的教训。”