View Full Version : [C#]Differenza fra || e | e fra & e &&
Mattyfog
30-05-2010, 11:10
Finalmente ho modo di studiare C#, su un libro non proprio stupendo (poichè a quanto ho letto è stato scritto prima per Visual Basic e poi convertito per C# lasciando purtroppo qua e là alcuni riferimenti al visual basic, però visto che l'ho avuto gratis non mi lamento) ma pur sempre un libro.
Dunque avrei una domanda.
Ho letto che gli operatori logici || e && sono ottimizzati rispetto a | e &. E il perchè sono più performanti l'ho capito.
A questo punto mi chiedevo: quand'è che può valer la pena usare ancora | e &?
| e & sono operatori bit a bit (servono per maneggiare i bit).
Ti faccio un esempio carino (più consono a C/C++):
Come saprai al carattere ascii 'A' è associato un valore intero: 65.
In binario:
100 0001
Cosa succede se vogliamo convertire il carattere 'A' nel minuscolo 'a'?
Vediamo che 'a' è codificato col numero 97:
110 0001
Guarda caso differiscono solo per un bit.
A questo punto per passare da 'A' ad 'a' possiamo pensare ad esempio di fare:
(65) 100 0001 OR
(32) 010 0000 =
-----------------
(97) 110 0001
Quindi se applichi l'istruzione:
'A' | 32
Ottieni 'a'.
Se volessimo ripassare da 'a' ad 'A', basterebbe fare un AND con una maschera del tipo:
(97) 110 0001 AND
(95) 101 1111 =
------------------
(32) 100 0001
Ti faccio un altro esempio... supponi tu voglia convertire il carattere '5' nel corrispondente intero 5.
Vediamo la tabella ascii:
011 0000 | 060 | 0
011 0001 | 061 | 1
011 0010 | 062 | 2
011 0011 | 063 | 3
011 0100 | 064 | 4
011 0101 | 065 | 5
011 0110 | 066 | 6
011 0111 | 067 | 7
011 1000 | 070 | 8
011 1001 | 071 | 9
Noti niente di particolare? Esatto, i primi 4 bit (da destra) rappresentano esattamente il numero intero in questione.
A questo punto basta "cestinare" gli ultimi 3 bit.
Prendiamo ad esempio 5:
(65) 011 0101 AND
(15) 000 1111 =
------------------
(05) 000 0101
Così facendo (X & 15) passi dal carattere all'intero corrispondente (chiaramente questo vale per 0 <= X <= 9).
oltre alle spiegazioni forniteti da WarDuck é bene precisare una cosa:
Ho letto che gli operatori logici || e && sono ottimizzati rispetto a | e &. E il perchè sono più performanti l'ho capito. e quale sarebbe il perché? a me non risulta affatto. la differenza tra i primi due e gli altri due é solamente che i primi due sono operatori booleani mentre gli altri sono bitwise. da che mi risulti funzionano tutti e quattro esattamente come in C, C++ e Java.
& e | controllano sempre tutte le condizioni. && e || no: nell'ipotesi di AND che la prima condizione sia false, non vengono controllate le restanti (perché il risultato è false in ogni caso). Per l'OR è lo stesso, se la prima è true le altre vengono saltate. Perciò è più performante. Inoltre possono succedere cose strane come:
a = 4;
b = 0:
# Nessun errore di divisione per zero
If (True || (a / b > 0)) { ... }
If (False && (a / b > 0)) { ... }
# Qui viene generata l'eccezione anche se non è necessario
controllare anche la seconda condizione, viene fatto lo stesso
If (True | (a / b > 0)) { ... }
If (False & (a / b > 0)) { ... }
Non ho mai avuto la necessità di usare & oppure |.
lupoxxx87
30-05-2010, 17:19
& e | controllano sempre tutte le condizioni.
non è che controllino sempre le condizioni...è che ci fanno delle operazioni algebriche
non è che controllino sempre le condizioni...è che ci fanno delle operazioni algebriche
...e come effetto controllano tutte le condizioni se messe in un If...
& e | controllano sempre tutte le condizioni. && e || no: nell'ipotesi di AND che la prima condizione sia false, non vengono controllate le restanti (perché il risultato è false in ogni caso). Per l'OR è lo stesso, se la prima è true le altre vengono saltate. Perciò è più performante. giusto: gli operatori bitwise per forza di cose sono eager mentre quelli booleani sono lazy.
Non ho mai avuto la necessità di usare & oppure |. in C/C++ capita spesso se si lavora con le API di Windows, le syscall di Linux o altro genere di interfacce di basso livello: capita spesso di dover riempire delle maschere di bit usando il bitwise OR e/o di dover testare dei bit in delle maschere usando il bitwise AND.
EDIT - e naturalmente, se il programmatore é un tipo particolarmente creativo, puó anche capitargli di dover invertire specifici bit di una maschera usando il bitwise XOR :)
giusto: gli operatori bitwise per forza di cose sono eager mentre quelli booleani sono lazy.
Bravo, una definizione ancora più precisa :)
@Mattyfog comunque sono cose che vengono spiegate (esattamente come ho scritto io) in qualsiasi libro di programmazione, anche al livello più elementare (cioè quelli che ti iniziano a spiegare i tipi e gli oggetti). ;)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.