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

10
demandé sur Dave 2009-02-18 15:59:31

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;
}
9
répondu eljenso 2009-02-18 15:34:41
 (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?

4
répondu Timbo 2009-02-18 13:29:06

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?

3
répondu John Leidegren 2009-02-18 13:08:15

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.

2
répondu starblue 2009-02-18 13:09:08

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
2
répondu Gumbo 2009-02-18 13:14:32

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.

0
répondu Adrian Pronk 2009-02-18 20:09:17

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:)

0
répondu Dave 2009-02-20 10:38:12