Successivo: Funzioni per i tipi, Precedente: Funzioni di tempo, Su: Funzioni predefinite [Contenuti][Indice]
Io posso spiegarlo per te, ma non posso capirlo per te.
Molti linguaggi consentono di eseguire operazioni bit a bit su due numeri interi. In altre parole, l’operazione è eseguita su ogni successiva coppia di bit presi da ognuno dei due operandi. Tre operazioni comuni sono AND, OR e XOR bit a bit. Queste operazioni sono descritte nella Tabella 9.6.
Operatore booleano | AND | OR | XOR |---+---+---+---+---+--- Operandi | 0 | 1 | 0 | 1 | 0 | 1 ----------+---+---+---+---+---+--- 0 | 0 0 | 0 1 | 0 1 1 | 0 1 | 1 1 | 1 0
Come si vede, il risultato di un’operazione di AND è 1 solo quando entrambi i bit sono 1. Il risultato di un’operazione di OR è 1 se almeno un bit è 1. Il risultato di un’operazione di XOR è 1 se l’uno o l’altro bit è 1, ma non tutti e due. La successiva operazione è il complemento; il complemento di 1 è 0 e il complemento di 0 è 1. Quindi, quest’operazione “inverte” tutti i bit di un dato valore.
Infine, due altre operazioni comuni consistono nello spostare i bit
a sinistra o a destra.
Per esempio, se si ha una stringa di bit ‘10111001’ e la si sposta
a destra di tre bit, si ottiene ‘00010111’.60
Partendo nuovamente da ‘10111001’ e spostandolo a sinistra di tre
bit, si ottiene ‘11001000’. La lista seguente descrive
le funzioni predefinite di gawk
che rendono disponibili
le operazioni a livello di bit.
I parametri opzionali sono racchiusi tra parentesi quadre ([ ]):
and(
v1,
v2 [,
…])
Restituisce l’AND bit a bit degli argomenti. Gli argomenti devono essere almeno due.
compl(val)
Restituisce il complemento bit a bit di val.
lshift(val, contatore)
Restituisce il valore di val, spostato a sinistra di contatore bit.
or(
v1,
v2 [,
…])
Restituisce l’OR bit a bit degli argomenti. Gli argomenti devono essere almeno due.
rshift(val, contatore)
Restituisce il valore di val, spostato a destra di contatore bit.
xor(
v1,
v2 [,
…])
Restituisce il XOR bit a bit degli argomenti. Gli argomenti devono essere almeno due.
ATTENZIONE: A partire dalla versione di
gawk
versione 4.2, gli operandi negativi non sono consentiti per nessuna di queste funzioni. Un operando negativo produce un errore fatale. Si veda la nota a lato “Attenzione. Non è tutto oro quel che luccica!” per maggiori informazioni sul perché.
Ecco una funzione definita dall’utente (vedi la sezione Funzioni definite dall’utente) che illustra l’uso di queste funzioni:
# bits2str --- decodifica un numero intero in una serie di 0/1 leggibili function bits2str(byte, dati, maschera) { if (byte == 0) return "0" maschera = 1 for (; byte != 0; stringa = rshift(stringa, 1)) dati = (and(byte, maschera) ? "1" : "0") dati while ((length(dati) % 8) != 0) dati = "0" dati return dati }
BEGIN { printf "123 = %s\n", bits2str(123) printf "0123 = %s\n", bits2str(0123) printf "0x99 = %s\n", bits2str(0x99) comp = compl(0x99) printf "compl(0x99) = %#x = %s\n", comp, bits2str(comp) shift = lshift(0x99, 2) printf "lshift(0x99, 2) = %#x = %s\n", shift, bits2str(shift) shift = rshift(0x99, 2) printf "rshift(0x99, 2) = %#x = %s\n", shift, bits2str(shift) }
Questo programma produce il seguente output quando viene eseguito:
$ gawk -f testbits.awk -| 123 = 01111011 -| 0123 = 01010011 -| 0x99 = 10011001 -| compl(0x99) = 0x3fffffffffff66 = -| 00111111111111111111111111111111111111111111111101100110 -| lshift(0x99, 2) = 0x264 = 0000001001100100 -| rshift(0x99, 2) = 0x26 = 00100110
La funzione bits2str()
trasforma un numero binario in una stringa.
Inizializzando maschera
a uno otteniamo
un valore binario in cui il bit più a destra è impostato a
uno. Usando questa maschera,
la funzione continua a controllare il bit più a destra.
l’operazione di AND tra la maschera e il valore indica se il
bit più a destra è uno oppure no. Se questo è il caso, un "1"
è concatenato all’inizio della stringa.
Altrimenti, è concatenato uno "0"
.
Il valore è quindi spostato a destra di un bit e il ciclo continua
finché non ci sono più bit.
Se il valore iniziale è zero, viene restituito semplicemente uno "0"
.
Altrimenti, alla fine, al valore ottenuto vengono aggiunti degli zeri a
sinistra, per arrivare a stringhe
di lunghezza multipla di 8, ossia contenenti un numero intero di byte.
Questo è tipico dei computer moderni.
Il codice principale nella regola BEGIN
mostra la differenza tra
i valori decimale e ottale dello stesso numero.
(vedi la sezione Numeri ottali ed esadecimali),
e poi mostra i risultati delle funzioni
compl()
, lshift()
e rshift()
.
Attenzione. Non è tutto oro quel che luccica!
In altri linguaggi, le operazioni "bit a bit" sono eseguite su valori interi, non su valori in virgola mobile. Come regola generale, tali operazioni funzionano meglio se eseguite su interi senza segno.
In una normale operazione, per tutte queste funzioni, prima il valore in virgola
mobile a doppia precisione viene convertito nel tipo intero senza segno di C
più ampio, poi viene eseguita l’operazione "bit a bit". Se il risultato non
può essere rappresentato esattamente come un tipo Comunque, quando si usa il calcolo con precisione arbitraria con l’opzione
-M (vedi la sezione Calcolo con precisione arbitraria con $ gawk 'BEGIN { print compl(42) }' -| 9007199254740949 $ gawk -M 'BEGIN { print compl(42) }' -| -43 Quel che avviene diventa chiaro quando si stampano i risultati in notazione esadecimale: $ gawk 'BEGIN { printf "%#x\n", compl(42) }' -| 0x1fffffffffffd5 $ gawk -M 'BEGIN { printf "%#x\n", compl(42) }' -| 0xffffffffffffffd5 Quando si usa l’opzione -M, nel dettaglio, In breve, usare |
Questo esempio
presuppone che degli zeri riempiano le posizioni a sinistra.
Per gawk
, è sempre
così, ma in alcuni linguaggi è possibile che le posizioni a sinistra
siano riempite con degli uno.
Per essere più chiari,
la conseguenza è che gawk
può memorizzare solo un determinato
intervallo di valori interi; i numeri al di fuori di questo intervallo vengono
ridotti per rientrare all’interno dell’intervallo.
Successivo: Funzioni per i tipi, Precedente: Funzioni di tempo, Su: Funzioni predefinite [Contenuti][Indice]