Que fait ET 0xFF?

Et 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 un type à un octet (comme uint8_t) ou est déjà inférieur à 256 (et par conséquent tous les zéros à l’exception de l’octet le moins significatif), il n’est pas nécessaire de masquer les bits les plus élevés, car ils sont déjà nuls.

Voir la réponse de tristopiaPatrick Schlüter ci-dessous lorsque vous travaillez peut-être avec des types signés. Lorsque vous effectuez des opérations au niveau du bit, je recommande de travailler uniquement avec des types non signés.

si byte1 est un type entier de 8 bits, cela 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

Le danger de la deuxième expression vient si le type de byte1 est char. Dans ce cas, certaines implémentations peuvent l’avoir signed char, ce qui entraînera une extension de signe 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 rightvalue2=65408 ff80 wrong!!

Je l’ai essayé sur gcc v3.4.6 sur Solaris SPARC 64 bits et le résultat est le même avec byte1 et byte2 déclarés comme char.

TL; DR

Le masquage est d’éviter l’extension de signe implicite.

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

EDIT2: Comme l’explique l’extension du signe.L’extension de signe est une conséquence de la façon dont C évalue les expressions. Il existe une règle en C appelée règle de promotion. C convertira implicitement tous les petits types en int avant de faire l’évaluation. Voyons ce qu’il advient de notre expression:

unsigned short value2 = ((byte2 << 8) | byte1);

byte1 est une variable contenant le motif de bits 0xFF. Si char vaut unsigned, cette valeur est interprétée comme 255, si elle vaut signed, elle vaut -128. Lors du calcul, C étendra la valeur à une taille int (généralement 16 ou 32 bits). Cela signifie que si la variable est unsigned et que nous garderons la valeur 255, le modèle de bits de cette valeur comme int sera 0x000000FF. Si c’est signed, nous voulons la valeur -128 dont le modèle de bits est 0xFFFFFFFF. Le signe a été étendu à la taille de la temporisation utilisée pour faire le calcul.Et ainsi oring le temporaire donnera le mauvais résultat.

Sur l’assemblage x86, cela se fait avec l’instruction movsx (movzx pour l’extension zéro). D’autres CPU avaient d’autres instructions pour cela (6809 avait SEX).

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.