web-dev-qa-db-ja.com

ビットごとのAND演算子について

Kochanの本「Objective-Cでのプログラミング」でObjective-Cのビット演算子について読んでいます。

これまでに提示された他のほとんどすべてを本当に理解しましたが、私はこの部分について非常に混乱しています。

これは本からの引用です:

ビットごとのAND演算子

ビット単位のAND演算は、マスキング操作によく使用されます。つまり、この演算子は、データ項目の特定のビットを0に設定するために簡単に使用できます。たとえば、次のステートメント

w3 = w1 & 3;

w3に定数3とビットごとのAND演算を行った値を割り当てます。これは、右端の2ビット以外のすべてのビットを0に設定し、w1の右端の2ビットを保持するのと同じ効果があります。

Cのすべてのバイナリ算術演算子と同様に、バイナリビット演算子も等号を追加することで代入演算子として使用できます。ステートメント

Word &= 15;

したがって、次と同じ機能を実行します。

Word = Word & 15;

さらに、Wordの右端の4ビットを除くすべてを0に設定する効果があります。定数をビット単位の演算の実行に使用する場合、通常、定数を8進または16進表記で表す方が便利です。

OK、それが私が理解しようとしていることです。今、私はこの全体の概念のほとんどに非常に混乱しています。誰かが私を手伝ってくれるかどうか、少し説明を求めています。

本が「すべてのビットを設定する」に言及するとき、すべてのビット..正確にはビットとは何ですか。それは2階の0または1、つまりバイナリではないですか?

もしそうなら、なぜ、最初の例では、「右端の2」を除くすべてのビットが0になっているのですか?定数から3を取って3-1なので、2ですか?

ありがとう!

49
Qcom

数値は次のようにバイナリで表現できます。

_3    = 000011
5    = 000101
10   = 001010
_

...等。あなたがバイナリに精通していると仮定します。

ビットごとのANDは、2つの数値を取り、それらを互いの上に並べ、1を持つ新しい数値を作成し、両方の数値が1である(それ以外はすべて0)ことを意味します。

例えば:

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

ビットごとのORは、2つの数値を取り、それらを互いの上に並べ、1を持つ新しい数値を作成します。一方、いずれかの数値が1である(それ以外はすべて0)。

例えば:

_    3          =>  00011
  | 5          =>  00101
------           -------
    7              00111
_

ビット単位XOR(exclusive OR))は、2つの数値を取り、それらを互いの上に並べ、1を持つ新しい数値を作成します。ここで、いずれかの数値に1があり、他の数値にはa 0(それ以外はすべて0)。

例えば:

_    3          =>  00011
  ^ 5          =>  00101
------           -------
    6              00110  
_

ビットワイズNOR(Not OR)は、ビットワイズORの2つの数値を取り、次にすべてを逆にします(0があったところ、1がここにあります) 1があったところが0になりました。

ビットワイズNAND(AND以外)は、2つの数値のビットワイズANDを取り、すべてを逆にします(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");
}
_

それを得る?

編集:その他のもの

また、「ビットシフト」演算子である<<と>>にも出会います。これは、「すべてをnビット左にシフト」または「すべてを右nビットシフト」を意味します。

言い換えると:

_1 << 3_ = _0001 << 3_ = _0001000_ = 8

そして:

_8 >> 2_ = _01000 >> 2_ = _010_ = 2

148
Dave DeLong

「ビット」は「2進数」の略です。はい、それは0または1です。ほとんどの場合、バイトには8があり、10進数のように書かれています-最上位の桁が左側に、最下位が右側にあります。

あなたの例では、w1 & 3は、2進数で3が00000011であるため、最下位(右端)の2桁を除くすべてをマスクします。(2 + 1)AND演算のいずれかのビットが0の場合、AND演算は0を返します。したがって、最後の2ビット以外はすべて自動的に0になります。

2
cHao
w1 =    ????...??ab
3  =    0000...0011
--------------------
&  =    0000...00ab

0&任意のビットN = 0

1および任意のビットN = N

したがって、ビット単位で3を付加したものはすべて、最後の2つを除くすべてのビットが0に設定されます。最後の2つのビット(この場合はaとb)が保持されます。

1
insipid

@cHao&all:No!ビットは数値ではありません。ゼロでも1でもありません。

まあ、0と1は可能で有効な解釈です。ゼロと1は典型的な解釈です。

しかし、少しはonly事であり、単純な代替を表します。 「ある」または「ない」と書かれています。それは「それ」そのものについては何も語っていません。それは何であるかを教えてくれません。

ほとんどの場合、これで気になりません。あなた(またはプログラミング言語、CPUと他のハードウェアの組み合わせ、「典型的」であることがわかっている)は、通常のようにそれらを数値(または数値、部分、数字)と見なすことができます。それら。

ただし、「0」と「1」の意味を入れ替えても問題はありません。わかりました。アセンブラのプログラミング中にこれを行うと、ニーモニックが他のロジックを実行するため、名前に問題があり、数字が否定されるなど、少し問題があることに気づくでしょう。

必要に応じて http://webdocs.cs.ualberta.ca/~amaral/courses/329/webslides/Topic2-DeMorganLaws/sld017.htm をご覧ください。

ご挨拶