Ripetiamo il giochetto dello scorso post: alzi la mano chi ha scritto recentemente codice che usa le operazioni bit a bit. Oppure, alzi la mano, senza prima andare a rileggersi un manuale del C, chi di voi sa usare e/o descrivere perfettamente le operazioni bit a bit. Uhmm... vedo poche mani alzate. Il fatto è che le bitwise operations sono una di quelle parti del C un po' misconosciute, di uso dubbio e infrequente, insomma una di quelle parti di cui, per mancanza di pratica ci si scorda (e ho usato esattamente le stesse parole dello scorso post: sono un ecologista, quando posso riciclo).
Rispetto alle union, oltretutto, devo dire che sulle operazioni bit a bit il fantastico K&R non è particolarmente chiaro e dettagliato, le tratta (come sono) come un argomento di nicchia, e non ti coinvolge con decine di divertenti esempi che ti aiutano a memorizzare definitivamente l'argomento, anzi, per quel che ricordo dell'ultima volta che lo lessi, sono un paio di pagine che scivolano via e che hai già dimenticato quando passi al prossimo capitolo. Beh anche la bibbia K&R (che io considero sacra) ha alcuni punti non proprio coinvolgenti.
Rinfreschiamo: gli operatori di bitwise (che operano sui singoli bit) sono:
Adesso, senza dilungarci in noiosi sproloqui, passiamo a una piccola tabella e ad alcuni semplici esempi pratici."&" AND "|" OR "^" XOR "~" NOT (complemento a 1) "<<" SHIFT a sinistra ">>" SHIFT a destra N.B.: - il NOT e' un operatore unario: opera su un solo argomento indicato sulla destra. - gli shift sono operatori unari: operano su un solo argomento indicato sulla sinistra.
Ecco la tabella:
Ed ecco i semplici esempi pratici:"&": il risultato è 1 se i due operandi valgono 1. Altrimenti 0. "|": il risultato è 0 se i due operandi valgono 0. Altrimenti 1. "^": il risultato è 1 se i due operandi sono diversi. Altrimenti 0. "~": il risultato è 1 se l'operando vale 0. Se l'operando vale 1 il risultato è 0. "<<n": il risultato è l'operando con tutti i bit spostati a sinistra di n posizioni. ">>n": il risultato è l'operando con tutti i bit spostati a destra di n posizioni.
Notare che nelle operazioni di shift i bit nuovi che entrano a destra (nello shift a sinistra) valgono 0, e i bit nuovi che entrano a sinistra (nello shift a destra) valgono 0.AND int a = 74; // 0 1 0 0 1 0 1 0 int b = 174; // 1 0 1 0 1 1 1 0 int c = a & b; // 0 0 0 0 1 0 1 0 risultato c=10 OR int a = 74; // 0 1 0 0 1 0 1 0 int b = 174; // 1 0 1 0 1 1 1 0 int c = a | b; // 1 1 1 0 1 1 1 0 risultato c=238 XOR int a = 74; // 0 1 0 0 1 0 1 0 int b = 174; // 1 0 1 0 1 1 1 0 int c = a ^ b; // 1 1 1 0 0 1 0 0 risultato c=228 NOT int a = 74; // 0 1 0 0 1 0 1 0 int b = ~a; // 1 0 1 1 0 1 0 1 risultato b=181 SHIFT a sinistra int a = 74; // 0 1 0 0 1 0 1 0 int b = a<<2; // 0 0 1 0 1 0 0 0 risultato b=296 SHIFT a destra int a = 74; // 0 1 0 0 1 0 1 0 int b = a>>2; // 0 0 0 1 0 0 1 0 risultato b=18
Notare anche che lo shift a destra equivale a una divisione per multipli di 2 (>>1 è una divisione per 2, >>2 è una divisione per 4, ecc.), mentre lo shift a sinistra equivale a una moltiplicazione per multipli di 2 (<<1 è una moltiplicazione per 2, <<2 è una moltiplicazione per 4, ecc.). Queste operazioni di moltiplicazione e divisione sono molto veloci, e si potrebbe essere tentati a usarle per velocizzare il codice: beh, prima di farlo rileggetevi (o leggetevi) questo.
E aggiungo un avvertimento: in base alla dimensione del tipo del operando e alla presenza o meno del bit di segno, le moltiplicazioni e divisioni con shift possono dare risultati inaspettati. Di questo ne parleremo in una prossima puntata, in cui faremo qualche esempio pratico di codice che usa le bitwise operations (e non trattenete il respiro, nel frattempo...).
Ciao e al prossimo post.
Lo so che sto scrivendo 7 anni dopo, ma volevo solo mostrarti un piccolo errore. Negli esempi ha messo & al posto di ^. Per il resto ottimo lavoro
RispondiEliminaGrazie mille "Anonimo", per i complimenti e per la segnalazione dell'errore. Ho corretto.
EliminaDi nulla ;)
Elimina