Bitwise et, Bitwise inclus ou question, en Java
j'ai quelques lignes de code dans un projet, dont je ne vois pas la valeur...
buffer[i] = (currentByte & 0x7F) | (currentByte & 0x80);
il lit le filebuffer à partir d'un fichier, stocké en octets, puis transfère ensuite dans le buffer[i] comme montré, mais je ne peux pas comprendre ce que l'objectif général est, des idées?
Merci
7 réponses
comme les autres réponses l'indiquent déjà, (currentByte & 0x7F) | (currentByte & 0x80)
équivaut à (currentByte & 0xFF)
. Le JLS3 15.22.1 dit Ceci est promu à un int
:
Lorsque les deux opérandes d'un opérateur &, ^ ou | sont d'un type qui est transformable (§5.1.8) en primitif type intégral, binaire numérique la promotion est d'abord effectuée sur opérandes (§5.6.2). Le type de la l'expression opérateur bitwise est promu type des opérandes.
parce que JLS3 5.6.2 dit que lorsque currentByte
a le type byte
et 0x7F
est un int
(et c'est le cas), alors les deux opérandes sont promues en int
.
par conséquent, buffer
sera un tableau du type d'élément int
ou plus large.
maintenant, en exécutant & 0xFF
sur un int
, nous cartographions effectivement le original byte
gamme -128..127 dans la fourchette 0 non signée..255, une opération souvent utilisée par java.io
streams par exemple.
Vous pouvez le voir en action dans l'extrait de code suivant. Notez que pour comprendre ce qui se passe ici, vous devez savoir que Java stocke les types intégraux, sauf char
, comme complément 2 valeurs.
byte b = -123;
int r = b;
System.out.println(r + "= " + Integer.toBinaryString(r));
int r2 = b & 0xFF;
System.out.println(r2 + "= " + Integer.toBinaryString(r2));
Enfin, pour un exemple réel, consultez la Javadoc et la mise en œuvre de la read
méthode de java.io.ByteArrayInputStream
:
/**
* Reads the next byte of data from this input stream. The value
* byte is returned as an <code>int</code> in the range
* <code>0</code> to <code>255</code>. If no byte is available
* because the end of the stream has been reached, the value
* <code>-1</code> is returned.
*/
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
(currentByte & 0x7F) | (currentByte & 0x80)
est l'équivalent de
currentByte & (0x7F | 0x80)
qui correspond à
currentByte & 0xFF
qui est exactement le même que
currentByte
Edit: Je n'ai regardé que le côté droit de la mission, et je pense toujours que l'équivalence est vraie.
cependant, il semble que le code veut lancer l'octet signé à un type plus grand tout en interprétant l'octet comme non signé.
est là une façon plus facile de lancer signé-byte à non signé en java?
je pense que quelqu'un a trop réfléchi ici. C'est tout simplement pas juste.
Je n'ai qu'une remarque
- l'auteur original s'est inquiété du fait que le temps d'exécution remplaçant le octet par un entier natif signé (probablement 32 bits) et essaie explicitement de nous dire quelque chose à propos du bit de signe étant"spécial"?
c'est le code laissé derrière. Sauf si tu sais que tu es sur une mauvaise passe? Quel est le type de le "tampon" de toute façon?
la logique bitwise compliquée est complètement superflue.
for (int i = 0; i < buffer.length; i++) {
buffer[i] = filebuffer[currentPosition + i] & 0xff;
}
fait la même chose. Si la mémoire tampon est déclaré comme un tableau d'octets, vous pouvez même laisser les & 0xff, mais malheureusement, la déclaration n'est pas montré.
la raison peut être que le développeur original était confus par les octets signés en Java.
le résultat d'un fonctionnement en bits a un 1 sur ces bits où les deux bits sont 1 alors que le résultat d'un fonctionnement en bits ou d'un fonctionnement en hase a sur ces bits où l'un des bits de bot est 1.
donc un exemple d'évaluation pour la valeur 0x65:
01100101 0x65
& 01111111 0x7F
===============
01100101 0x65
01100101 0x65
& 10000000 0x80
===============
00000000 0x00
01100101 0x65
| 00000000 0x00
===============
01100101 0x65
La bonne chose à propos de ces sortes d'opérations logiques: vous pouvez essayer toutes les combinaisons possibles (256) et vérifiez que vous obtenez la réponse que vous attendiez.
S'avère, le fichier dont l'octet était lu était dans une notation bit signée, et d'une longueur différente, donc il a été requuried pour effectuer cette tâche pour permettre à elle d'être étendue au type int java, tout en conservant son signe correct:)