Qu'est-ce que does AND 0xFF fait?
Dans le code suivant:
short = ((byte2 << 8) | (byte1 & 0xFF))
Quel est le but de &0xFF
?
Parce que d'autres estiment que je le vois écrit comme:
short = ((byte2 << 8) | byte1)
et ça a l'air de marcher aussi?
7 réponses
Anding un entier 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
. C'est généralement appelé "masque". Si byte1
est un type octet (comme uint8_t
) ou est déjà inférieur à 256 (et par conséquent tous les zéros sauf pour le octet le moins significatif) il n'y a pas besoin de masquer les bits supérieurs, car ils sont déjà zéro.
Voir tristopiaréponse de Patrick Schlüter ci-dessous quand vous pouvez travailler avec des types signés. Lorsque vous effectuez des opérations bitwise, je vous recommande de travailler uniquement avec des types non signés.
si byte1
est un type entier 8 bits alors il est inutile - 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
Le danger de la seconde expression vient, si le type de byte1
char
. Dans ce cas, certaines implémentations peuvent avoir signed char
, ce qui entraînera une extension du signal 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);
value1=4224 1080 right
value2=65408 ff80 wrong!!
j'ai essayé sur gcc v3.4.6 sur Solaris SPARC 64 bit et le résultat est le même avec byte1
et byte2
a déclaré que char
.
TL;DR
Le masquage pour éviter implicite signe extension.
EDIT: j'ai vérifié, c'est le même comportement en C++.
en supposant votre byte1
est un octet(8bits), Lorsque vous effectuez une opération de bits ET d'octets avec 0xFF, vous obtenez le même octet.
byte1
est le même que byte1 & 0xFF
byte1
01001101
, puis byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1
si byte1 est d'un autre type dire entier de 4 octets, bitwise et avec 0xFF vous laisse avec le moins significatif byte (8 bits) du byte1.
byte1 & 0xff
assure que seuls les 8 bits les moins significatifs de byte1
peut être non nulle.
si byte1
est déjà un type non signé qui n'a que 8 bits (e.g.,char
dans certains cas, ou unsigned char
dans la plupart des cas) cela ne fera aucune différence/est complètement inutile.
Si byte1
est un type qui est signé ou a plus de 8 bits (par exemple,short
,int
,long
), et tous les bits sauf le 8 le moins significatif est définie, alors il y aura une différence (c'est à dire, il va de zéro ces bits de poids avant or
avec l'autre variable, donc cet opérande du or
affecte seulement les 8 bits les moins significatifs du résultat).
il efface tous les bits qui ne sont pas dans le premier octet
& 0xFF
garantit seulement que si les octets sont plus longs que 8 bits (autorisés par la norme de langue), le reste est ignoré.
Et qui semble bien fonctionner aussi?
si le résultat est supérieur à SHRT_MAX
, vous obtenez un comportement indéfini. À cet égard, les deux ne fonctionneront pas aussi bien.