了解按位与运算符
Posted
技术标签:
【中文标题】了解按位与运算符【英文标题】:Understanding the bitwise AND Operator 【发布时间】:2011-03-26 13:11:31 【问题描述】:我一直在 Kochan 的《Objective-C 编程》一书中阅读有关 Objective-C 中位运算符的内容。
我对这部分感到非常困惑,尽管到目前为止我已经真正理解了大多数其他呈现给我的东西。
这是书中的一段话:
位与运算符
按位与经常用于屏蔽操作。也就是说,可以很容易地使用该运算符将数据项的特定位设置为 0。例如,语句
w3 = w1 & 3;
将 w1 的值与常量 3 按位与运算分配给 w3。这与将 w 中的所有位设置为相同的效果,除了最右边的两位为 0 并保留 w1 的最右边的两位。
与 C 中的所有二进制算术运算符一样,二进制位运算符也可以通过添加等号用作赋值运算符。声明
word &= 15;
因此执行与以下相同的功能:
word = word & 15;
此外,它还具有将 word 的最右边四位以外的所有位设置为 0 的效果。在执行按位运算时使用常量时,通常以八进制或十六进制表示法表示常量更方便。
好的,这就是我想要理解的。现在,我对几乎整个概念都感到非常困惑,如果有人愿意帮助我,我只是想澄清一下。
当本书现在提到“设置所有位”时,所有位..究竟是什么位。这不就是二基数的 0 或 1,也就是二进制吗?
如果是这样,为什么在第一个示例中,除了“最右边的 2”之外的所有位都为 0?是 2 因为它是 3 - 1,从我们的常数中取 3?
谢谢!
【问题讨论】:
【参考方案1】:数字可以像这样用二进制表示:
3 = 000011
5 = 000101
10 = 001010
...等等。我假设你熟悉二进制。
按位与表示取两个数字,将它们排成一行,然后创建一个新数字,其中两个数字都为 1(其他数字均为 0)。
例如:
3 => 00011
& 5 => 00101
------ -------
1 00001
按位或表示取两个数字,将它们排成一行,然后创建一个新数字,其中一个数字为 1(其他数字均为 0)。
例如:
3 => 00011
| 5 => 00101
------ -------
7 00111
按位异或(异或)意味着取两个数字,将它们排在彼此的顶部,并创建一个新的数字,其中一个数字为 1,另一个数字为 0(其他的都是0).
例如:
3 => 00011
^ 5 => 00101
------ -------
6 00110
按位或非(非或)意味着取两个数的按位或,然后将所有内容取反(原来是 0,现在是 1,原来是 1,现在是 0)。
按位与非(非与)意味着取两个数字的按位与,然后反转所有内容(有 0 的地方现在有 1,有 1 的地方现在有 0)。
继续:为什么word &= 15
将除了最右边的 4 位之外的所有位都设置为 0?你现在应该可以弄清楚了……
n => abcdefghjikl
& 15 => 000000001111
------ --------------
? 00000000jikl
(0 AND a = 0
, 0 AND b = 0
, ...j AND 1 = j
, i AND 1 = i
, ...)
这有什么用?在许多语言中,我们使用称为“位掩码”的东西。位掩码本质上是一个数字,代表一大堆组合在一起的较小数字。我们可以使用 OR 将数字组合在一起,并使用 AND 将它们分开。例如:
int MagicMap = 1;
int MagicWand = 2;
int MagicHat = 4;
如果我只有地图和帽子,我可以将其表示为myInventoryBitmask = (MagicMap | MagicHat)
,结果就是我的位掩码。如果我什么都没有,那么我的位掩码是 0。如果我想看看我是否有我的魔杖,那么我可以这样做:
int hasWand = (myInventoryBitmask & MagicWand);
if (hasWand > 0)
printf("I have a wand\n");
else
printf("I don't have a wand\n");
明白了吗?
编辑:更多内容
您还会遇到“bitshift”运算符:>。这只是意味着“将所有内容左移 n 位”或“将所有内容右移 n 位”。
换句话说:
1 << 3
= 0001 << 3
= 0001000
= 8
还有:
8 >> 2
= 01000 >> 2
= 010
= 2
【讨论】:
哇!非常感谢您的回复。根据这个在线计算器:convertit.com/go/convertit/calculators/math/base_converter.asp 3 = 11 5 = 101 10 = 1010 您是否在二进制数字前加了前缀或类似的东西? @BOSS 是的,我以 0 为前缀,以使它们对齐并确保它们不是负的“2s-complement”数字。 @Dave 好的,谢谢,我以前在某处听说过,我猜每个二进制数都以 1 开头?无论如何,对于带有单词 &= 15 的示例仍然有点困惑。让我看看我是否明白了:基本上,正如你所说,因为 j 和 1 = j,这是因为有一个 1,而有点不是' 0?相反,0 AND a = 0 因为没有 1 与 a 配对? @BOSS 是的,你明白了!想一想的话会有所帮助:YES AND NO = NO
、YES OR NO = YES
、YES NOR NO = NOT(YES OR NO) = NO
等。
@BOSS 他们非常有用。它之所以有效,是因为您基本上将位掩码的每个“列”视为代表一个项目(在此示例中为您的库存)的“开/关开关”。您定义的项目使得(在二进制中)它们只有一个 1,其余的都是 0。这意味着您可以将它们组合在一起而不会丢失任何信息。它真的很有用,你会在 Cocoa 中看到很多(大多数具有 options:
参数的方法都要求提供选项的位掩码)【参考方案2】:
“位”是“二进制数字”的缩写。是的,它是 0 或 1。一个字节中几乎总是有 8 个,它们的写法有点像十进制数字——最重要的数字在左边,最不重要的数字在右边。
在您的示例中,w1 & 3
屏蔽了除两个最低有效(最右边)数字之外的所有内容,因为二进制中的 3 是 00000011。(2 + 1) 如果任一位被与为 0,则 AND 操作返回 0,所以一切但最后两位自动为 0。
【讨论】:
【参考方案3】:w1 = ????...??ab
3 = 0000...0011
--------------------
& = 0000...00ab
0 & 任意位 N = 0
1 & 任意位 N = N
因此,任何与 3 进行按位与运算的所有位都将除最后两位设置为 0。最后两位(在本例中为 a 和 b)被保留。
【讨论】:
【参考方案4】:@cHao & all:不!位不是数字。它们不是零或一!
嗯,0 和 1 是可能且有效的解释。零和一是典型的解释。
但有点只是一个东西,代表一个简单的选择。它说“它是”或“它不是”。它没有说明事物本身,即“它”。它不知道它是什么。
在大多数情况下,这不会打扰您。您可以将它们用作数字(或数字的部分、数字),就像您(或编程语言、cpu 和其他硬件的组合,您知道是“典型的”)通常所做的那样——也许您永远不会遇到麻烦他们。
但是,如果将“0”和“1”的含义互换,则没有主要问题。好吧,如果在编写汇编程序时这样做,你会发现它有点问题,因为一些助记符会做其他逻辑然后他们告诉你他们的名字,数字将被否定等等。
如果需要,请查看http://webdocs.cs.ualberta.ca/~amaral/courses/329/webslides/Topic2-DeMorganLaws/sld017.htm。
问候
【讨论】:
喜欢这个答案的华夫饼。位既不是零也不是一!...除非它们用 0 和 1 表示,这是典型的表示。但是如果你切换“0”和“1”的含义是没有问题的……除非你是用汇编程序编程,否则就有问题了。这种观点介于无用的迂腐和疯狂之间。 听起来像是纯粹主义的受害者。以上是关于了解按位与运算符的主要内容,如果未能解决你的问题,请参考以下文章