web-dev-qa-db-fra.com

Que fait AND 0xFF?

Dans le code suivant:

short = ((byte2 << 8) | (byte1 & 0xFF))

Quel est le but de &0xFF? Parce que parfois je le vois écrit comme:

short = ((byte2 << 8) | byte1)

Et cela semble bien fonctionner aussi?

35
Muis

Anding un entier avec 0xFF ne laisse que l'octet le moins significatif. Par exemple, pour obtenir le premier octet dans un short s, vous pouvez écrire s & 0xFF. Ceci est généralement appelé "masquage". Si byte1 est soit un type à un seul octet (comme uint8_t) ou est déjà inférieur à 256 (et a donc pour résultat des zéros à l'exception de l'octet le moins significatif), il n'est pas nécessaire de masquer les bits supérieurs, car ils sont déjà nuls.

Voir tristopiaLa réponse de Patrick Schlüter ci-dessous lorsque vous travaillez avec des types signés. Lorsque vous effectuez des opérations au niveau des bits, je vous recommande de ne travailler qu'avec des types non signés.

33
John Colanduoni

si byte1 est un type entier de 8 bits, il ne sert à rien, s'il est supérieur à 8 bits, il vous donnera essentiellement les 8 derniers bits de la valeur:

    0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
 &  0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
    -------------------------------
    0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1
24
D Stanley

Le danger de la deuxième expression survient si le type de byte1 est char. Dans ce cas, certaines implémentations peuvent avoir signed char, ce qui entraînera une extension de signature lors de l'évaluation.

signed char byte1 = 0x80;
signed char byte2 = 0x10;

unsigned short value1 = ((byte2 << 8) | (byte1 & 0xFF));
unsigned short value2 = ((byte2 << 8) | byte1);

printf("value1=%hu %hx\n", value1, value1);
printf("value2=%hu %hx\n", value2, value2);

imprimera

value1=4224 1080     right
value2=65408 ff80    wrong!!

Je l’ai essayé sur gcc v3.4.6 sur Solaris SPARC 64 bits et le résultat est identique à byte1 et byte2 déclaré comme char.

TL; DR

Le masquage consiste à éviter l’extension de signe implicite.

EDIT: J'ai vérifié, c'est le même comportement en C++.

19
Patrick Schlüter

En supposant que votre byte1 est un octet (8bits), lorsque vous effectuez un ET au niveau des bits d'un octet avec 0xFF, vous obtenez le même octet.

Donc, byte1 est identique à byte1 & 0xFF

Disons que byte1 est 01001101, puis byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1

Si octet1 est d'un autre type, par exemple un entier de 4 octets, AND au niveau du bit AND avec 0xFF vous laisse avec l'octet le moins significatif (8 bits) de l'octet1. 

6
Sibi Rajasekaran

Le byte1 & 0xff garantit que seuls les 8 bits les moins significatifs de byte1 peuvent être non nuls.

si byte1 est déjà un type non signé qui n'a que 8 bits (par exemple, char dans certains cas, ou unsigned char dans la plupart des cas), cela ne fera aucune différence/est totalement inutile.

Si byte1 est un type signé ou comporte plus de 8 bits (par exemple, short, int, long) et que l’un des bits sauf le 8 moins significatif soit défini, il y aura une différence les bits supérieurs avant oring avec l’autre variable, donc cet opérande de or n’affecte que les 8 bits les moins significatifs du résultat).

3
Jerry Coffin

il efface tous les bits qui ne sont pas dans le premier octet

1
thumbmunkeys

& 0xFF seul garantit que, si les octets sont plus longs que 8 bits (autorisés par la norme de langue), les autres sont ignorés.

Et cela semble bien fonctionner aussi?

Si le résultat est supérieur à SHRT_MAX, vous obtenez un comportement indéfini. À cet égard, les deux fonctionneront également mal.

0
Alexey Frunze