Domanda

Ho un paio di righe di codice all'interno di un progetto, che non riesco a vedere il valore di ...

buffer[i] = (currentByte & 0x7F) | (currentByte & 0x80);

E 'legge il filebuffer da un file, memorizzato come byte, e poi trasferisce poi al buffer [i] Come mostrato, ma non riesco a capire quale sia lo scopo generale è, tutte le idee?

Grazie

È stato utile?

Soluzione

Come le altre risposte già detto, (currentByte & 0x7F) | (currentByte & 0x80) equivale a (currentByte & 0xFF). Il JLS3 15.22.1 dice che questo è promosso a un int:

  

Quando entrambi gli operandi di un operatore e,   ^ O | sono di un tipo che è   convertibile (§5.1.8) per un primitivo   tipo integrale, numerico binario   la promozione viene eseguita prima sulla   operandi (§5.6.2). Il tipo di   bitwise espressione è l'operatore   tipo promosso degli operandi.

5.6.2 dice che quando currentByte ha tipo byte e 0x7F è int (e questo è il caso), quindi entrambi vengono promosso int.

Pertanto, buffer sarà un array di tipo di elemento int o più ampio.

Ora, eseguendo & 0xFF su un int, mappiamo efficacemente la gamma byte originale -128..127 nella gamma unsigned 0..255, operazione spesso usato dai java.io flussi per esempio.

È possibile vedere in azione nel seguente frammento di codice. Si noti che per capire cosa sta succedendo qui, dovete sapere che memorizza Java tipi integrali, ad eccezione char, come complemento a 2 valori.

byte b = -123;
int r = b;
System.out.println(r + "= " + Integer.toBinaryString(r));
int r2 = b & 0xFF;
System.out.println(r2 + "= " + Integer.toBinaryString(r2));

Infine, per un esempio reale, controllare il Javadoc e l'attuazione del metodo di read 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;
}

Altri suggerimenti

 (currentByte & 0x7F) | (currentByte & 0x80)

è equivalente a

 currentByte & (0x7F | 0x80)

che è uguale a

 currentByte & 0xFF

che è esattamente lo stesso di

 currentByte

Edit: ho guardato solo al lato destro del compito, e io continuo a pensare che l'equivalenza è vero

.

Tuttavia, sembra che il codice vuole lanciare il byte firmato per un tipo più grande interpretando il byte come senza segno.

C'è un modo più semplice per lanciare firmato byte per non firmato in java?

Credo che qualcuno ha troppo a pensare qui. Questo non è giusto.

Ho solo un'osservazione

  • L'autore originale era preoccupato per la fase di esecuzione sostituendo il byte con un intero nativo firmato (presumibilmente a 32 bit) ed è esplicitamente cercando di dirci qualcosa circa il bit del segno di essere "speciale"?

E 'il codice lasciato alle spalle. Se non si sa che sei un pesce di run-time? Qual è il tipo di 'buffer' comunque?

La logica bitwise complicato è del tutto superflua.

for (int i = 0; i < buffer.length; i++) {
    buffer[i] = filebuffer[currentPosition + i] & 0xff;
}

fa la stessa cosa. Se buffer è dichiarato come un array di byte si può anche lasciare fuori il & 0xFF, ma purtroppo la dichiarazione non viene visualizzato.

Il motivo può essere che lo sviluppatore originale è stato confuso da byte di essere firmato in Java.

Il risultato di un'operazione AND di bit ha un 1 su che i bit in cui entrambi i bit sono 1, mentre il risultato di un'operazione OR hase una su tale bit dove uno di bit Bot è 1.

Quindi, una valutazione ad esempio per il valore 0x65:

  01100101 0x65
& 01111111 0x7F
===============
  01100101 0x65

  01100101 0x65
& 10000000 0x80
===============
  00000000 0x00

  01100101 0x65
| 00000000 0x00
===============
  01100101 0x65

La cosa buona di questo tipo di operazioni logiche:. Si può provare ogni possibile combinazione (tutti 256 di loro) e verificare che si ottiene la risposta che vi aspettavate

Si scopre che, il file che il byte è in corso la lettura era in una notazione bit con segno, e di una lunghezza diversa, quindi è stato requried per eseguire questa operazione per permettere di essere esteso al tipo int Java, pur mantenendo il suo corretto segno:)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top