web-dev-qa-db-fra.com

Comprendre l'opérateur AND au niveau du bit

J'ai lu sur les opérateurs de bits dans Objective-C dans le livre de Kochan, "Programmation dans Objective-C".

Je suis TRÈS confus à propos de cette partie, même si j'ai vraiment compris presque tout le reste qui m'a été présenté jusqu'à présent.

Voici une citation du livre:

l'opérateur ET au niveau du bit

L'AND au niveau du bit est fréquemment utilisé pour les opérations de masquage. Autrement dit, cet opérateur peut être utilisé facilement pour définir des bits spécifiques d'un élément de données à 0. Par exemple, l'instruction

w3 = w1 & 3;

assigne à w3 la valeur de w1 au niveau du bit ET avec la constante 3. Cela a le même effet de mettre tous les bits de w, autres que les deux bits les plus à droite à 0 et de préserver les deux bits les plus à droite de w1.

Comme avec tous les opérateurs arithmétiques binaires en C, les opérateurs de bits binaires peuvent également être utilisés comme opérateurs d'affectation en ajoutant un signe égal. La déclaration

Word &= 15;

remplit donc la même fonction que la suivante:

Word = Word & 15;

En outre, cela a pour effet de définir tous les bits de Word sauf les quatre à droite sur 0. Lorsque vous utilisez des constantes pour effectuer des opérations au niveau du bit, il est généralement plus pratique d'exprimer les constantes en notation octale ou hexadécimale.

OK, c'est ce que j'essaie de comprendre. Maintenant, je suis extrêmement confus avec à peu près tout ce concept et je cherche juste une petite clarification si quelqu'un est prêt à m'aider à ce sujet.

Quand le livre fait référence à "mettre tous les bits" maintenant, tous les bits. Qu'est-ce qu'un bit exactement. N'est-ce pas juste un 0 ou 1 en 2e base, en d'autres termes, binaire?

Si c'est le cas, pourquoi, dans le premier exemple, tous les bits, à l'exception du "2 le plus à droite", sont-ils à 0? Est-ce 2 parce que c'est 3 - 1, en prenant 3 de notre constante?

Merci!

49
Qcom

Les nombres peuvent être exprimés en binaire comme ceci:

3    = 000011
5    = 000101
10   = 001010

...etc. Je vais supposer que vous connaissez le binaire.

ET au niveau du bit signifie prendre deux nombres, les aligner les uns sur les autres et créer un nouveau nombre qui a un 1 où les deux nombres ont un 1 (tout le reste est 0).

Par exemple:

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

Bitwise OR signifie prendre deux nombres, les aligner les uns sur les autres et créer un nouveau nombre qui a un 1 où l'un ou l'autre a un 1 (tout le reste est 0).

Par exemple:

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

Bitwise XOR (OU exclusif) signifie prendre deux nombres, les aligner les uns sur les autres et créer un nouveau nombre qui a un 1 où l'un ou l'autre a un 1 ET l'autre a un 0 (tout le reste est 0).

Par exemple:

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

Bitwise NOR (Not OR) signifie prendre le Bitwise OR de deux nombres, puis inverser tout (là où il y avait un 0, il y a maintenant un 1, là où il y avait un 1, il y a maintenant un 0).

NAND au niveau du bit (pas ET) signifie prendre le ET au niveau du bit de deux nombres, puis inverser tout (où il y avait un 0, il y a maintenant un 1, où il y avait un 1, il y a maintenant un 0).

Continue: pourquoi Word &= 15 Met-il tous les bits sauf les 4 les plus à droite à 0? Vous devriez pouvoir le comprendre maintenant ...

     n          =>  abcdefghjikl
  & 15          =>  000000001111
------            --------------
     ?              00000000jikl

(0 AND a = 0, 0 AND b = 0, ... j AND 1 = j, i AND 1 = i, ...)

Comment est-ce utile? Dans de nombreuses langues, nous utilisons des choses appelées "bitmasks". Un masque de bits est essentiellement un nombre qui représente tout un tas de petits nombres combinés ensemble. Nous pouvons combiner des nombres à l'aide de OU et les séparer à l'aide de ET. Par exemple:

int MagicMap = 1;
int MagicWand = 2;
int MagicHat = 4;

Si je n'ai que la carte et le chapeau, je peux l'exprimer sous la forme myInventoryBitmask = (MagicMap | MagicHat) et le résultat est mon masque de bits. Si je n'ai rien, alors mon bitmask est 0. Si je veux voir si j'ai ma baguette, alors je peux faire:

int hasWand = (myInventoryBitmask & MagicWand);
if (hasWand > 0) {
  printf("I have a wand\n");
} else {
  printf("I don't have a wand\n");
}

Tu piges?

EDIT: plus de choses

Vous rencontrerez également l'opérateur "bitshift": << et >>. Cela signifie simplement "décaler tout à gauche n bits" ou "décaler tout à droite n bits".

En d'autres termes:

1 << 3 = 0001 << 3 = 0001000 = 8

Et:

8 >> 2 = 01000 >> 2 = 010 = 2

148
Dave DeLong

"Bit" est l'abréviation de "chiffre binaire". Et oui, c'est un 0 ou un 1. Il y a presque toujours 8 dans un octet, et ils sont écrits un peu comme les nombres décimaux - avec le chiffre le plus significatif à gauche et le moins significatif à droite.

Dans votre exemple, w1 & 3 masque tout sauf les deux chiffres les moins significatifs (les plus à droite), car 3, en binaire, est 00000011. (2 + 1) L'opération AND renvoie 0 si l'un des bits AND est 0, donc tout sauf les deux derniers bits est automatiquement 0 .

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

0 et tout bit N = 0

1 & tout bit N = N

Donc, tout ce qui est bit à bit et avec 3 a tous ses bits sauf les deux derniers mis à 0. Les deux derniers bits, a et b dans ce cas, sont conservés.

1
insipid

@cHao & all: Non! Les bits ne sont pas des nombres. Ils ne sont ni zéro ni un!

Eh bien, 0 et 1 sont des interprétations possibles et valides. Zéro et un est l'interprétation typique.

Mais un peu est seulement une chose, représentant une alternative simple. Il dit "c'est" ou "ce n'est pas". Il ne dit rien sur la chose, le "ça" lui-même. Ça ne dit pas ce que c'est.

Dans la plupart des cas, cela ne vous dérangera pas. Vous pouvez les prendre pour des nombres (ou des parties, des chiffres, des nombres) comme vous (ou la combinaison de langages de programmation, d'unités centrales et d'autres matériels, vous savez comme étant "typiques"), et vous n'aurez peut-être jamais de problème avec leur.

Mais il n'y a pas de problème principal si vous changez la signification de "0" et "1". Ok, si vous faites cela lors de la programmation de l'assembleur, vous trouverez cela un peu problématique car certains mnémoniques feront une autre logique puis ils vous le diront avec leurs noms, les nombres seront annulés et ainsi de suite.

Jetez un œil à http://webdocs.cs.ualberta.ca/~amaral/courses/329/webslides/Topic2-DeMorganLaws/sld017.htm si vous le souhaitez.

Salutations