Bitwise operators

Riporto qui un semplice metodo per recuperare il valore incorporato in un byte, nel caso in cui si abbiano più informazioni entro un unico byte:

image

C#:
private static int GetBits(byte b, int offset, int length)
{
    // shifta di un numero di volte pari a offset
    b >>= offset;

    // esegui mascheratura
    b &= (byte)((1 << length) - 1);

    return b;
}

Se vi è chiaro ciò che fa questa funzione, e in particolare l’operazione di mascheratura, saltate pure il resto, altrimenti forse è il caso di fare un piccolo ripasso delle operazioni bitwise.

Prima di affrontare il caso generale vediamo due semplici metodi di estrazione, applicati ad un esempio concreto.

La specifica MIDI del Meta Evento “SMPTE Offset” prevede una sequenza di byte così fatta:

image

dove il byte che contiene l’ora contiene anche il valore di frame rate:

image

e impone che il bit più significativo (quello più a sinistra, per intenderci) sia sempre pari a zero.

Operazione di Mascheratura:

Volendo recuperare il valore di “hour”, dobbiamo mascherare (cioè rendere nulli) gli altri bit. Useremo quindi una maschera con i tre bit più significativi (ovvero “più a sinistra”) pari a zero e i restanti pari a 1:

image

C#:
hour = theByte & 31;

dove 31 è il valore decimale di “00011111” e “&” è l’operatore logico AND, eseguito bit su bit.

Operazione di Shift:

Volendo recuperare il valore di frame rate, in questo caso specifico, basta spostare i bit verso destra di cinque posizioni:

image

C#:
frameRate = theByte >> 5;

Il caso generale:

In generale, volendo recuperare il valore relativo ad una porzione di byte, dobbiamo combinare le due precedenti tecniche, prima shiftando e poi mascherando, come riportato nella funzione di cui sopra.

Per illustrare la parte interessante, ovvero la creazione della maschera, utilizziamo un esempio concreto:

image

dopo l’operazione di shifting si ha:

image

Appare evidente che mascheratura va effettuata con una maschera pari a:

image

Ma in generale, come possiamo costruire la maschera a partire dai paramentri “offset” e “length” ?

La risposta è semplice se consideriamo l’equivalenza:

image

Dunque per creare la maschera ci basta prendere “00000001”, shiftarlo verso sinista di un numero di volte pari a “length” e sottrargli “00000001”.

C#:
// Crea maschera - step 1
byte mask = 1;

// Crea maschera - step 2 (shifta di un numero di volte pari a length)
mask <<= length;

// Crea maschera - step 3 (sottrai 1)
mask -= 1;

Da notare che nella routine, poiché la maschera viene creata “al volo” in un’unica riga, occorre esplicitare che le operazioni di shift e di sottrazione sono da effettuare sul tipo byte (e non su int32, come farebbe il compilatore). Ed è per questo motivo che viene usato il casting esplicito a (byte) senza il quale il compilatore si rifiuta di compilare visto che un casting implicito da int32 a byte provocherebbe un’evidente possibilità di perdita di dati.

That’s all folks!

«novembre»
domlunmarmergiovensab
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910