49

我一直在 Kochan 的书“Objective-C 编程”中阅读有关 Objective-C 中的位运算符的内容。

我对这部分感到非常困惑,尽管到目前为止我已经真正理解了大多数其他呈现给我的东西。

这是书中的一段话:

按位与运算符

按位与经常用于屏蔽操作。也就是说,可以很容易地使用该运算符将数据项的特定位设置为 0。例如,语句

w3 = w1 & 3;

将 w1 的值与常数 3 按位与运算分配给 w3。这与将 w 中的所有位设置为相同的效果,除了最右边的两位为 0 并保留来自 w1 的最右边的两位。

与 C 中的所有二进制算术运算符一样,二进制位运算符也可以通过添加等号用作赋值运算符。该声明

word &= 15;

因此执行与以下相同的功能:

word = word & 15;

此外,它还具有将字的最右边四位以外的所有位设置为 0 的效果。在执行按位运算时使用常量时,以八进制或十六进制表示法表示常量通常更方便。

好的,这就是我想要理解的。现在,我对几乎整个概念都感到非常困惑,如果有人愿意帮助我,我只是想澄清一下。

当本书现在引用“设置所有位”时,所有位..究竟是什么。这不只是二基数的 0 或 1,换句话说,二进制吗?

如果是这样,为什么在第一个示例中,除了“最右边的 2”之外的所有位都为 0?是 2 因为它是 3 - 1,从我们的常数中取 3?

谢谢!

4

4 回答 4

150

数字可以用二进制表示,如下所示:

3    = 000011
5    = 000101
10   = 001010

...ETC。我假设你熟悉二进制。

按位与表示取两个数字,将它们排成一行,然后创建一个新数字,其中两个数字都为 1(其他数字均为 0)。

例如:

    3          =>  00011
  & 5          =>  00101
------           -------
    1              00001

按位或表示取两个数字,将它们排成一行,然后创建一个新的数字,该数字为 1,其中任一数字为 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

于 2010-08-06T20:40:15.057 回答
2

“位”是“二进制数字”的缩写。是的,它是 0 或 1。一个字节中几乎总是有 8 个,它们的写法有点像十进制数字——最高有效位在左边,最低有效位在右边。

在您的示例中,w1 & 3屏蔽除两个最低有效(最右边)数字之外的所有内容,因为二进制中的 3 为 00000011。(2 + 1)如果与运算的任一位为 0,则与运算返回 0,因此除最后两位之外的所有内容都是自动 0。

于 2010-08-06T20:41:12.473 回答
1
w1 =    ????...??ab
3  =    0000...0011
--------------------
&  =    0000...00ab

0 & 任何位 N = 0

1 & 任何位 N = N

因此,与 3 进行按位与运算的任何位都将除最后两位设置为 0 之外的所有位。最后两位,在本例中为 a 和 b,将被保留。

于 2010-08-06T20:48:55.163 回答
1

@cHao & all:不!位不是数字。它们不是零或一!

那么,0 和 1 是可能且有效的解释。零和一是典型的解释。

但一点只是一个东西,代表一个简单的选择。它说“它是”或“它不是”。它没有说明事物本身,即“它”本身。它不告诉,它是什么东西。

在大多数情况下,这不会打扰您。您可以将它们用作数字(或数字的部分、数字),就像您(或编程语言、cpu 和其他硬件的组合,您知道是“典型的”)一样 - 也许您永远不会遇到麻烦他们。

但是,如果将“0”和“1”的含义互换,则没有主要问题。好的,如果在编写汇编程序时这样做,你会发现它有点问题,因为一些助记符会做其他逻辑然后他们告诉你他们的名字,数字将被否定等等。

如果需要,请查看http://webdocs.cs.ualberta.ca/~amaral/courses/329/webslides/Topic2-DeMorganLaws/sld017.htm 。

问候

于 2010-08-07T18:58:28.263 回答