PDA

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 &?

WarDuck
30-05-2010, 11:41
| 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

WarDuck
30-05-2010, 12:00
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).

fero86
30-05-2010, 13:57
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.

Gremo
30-05-2010, 15:44
& 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

Gremo
30-05-2010, 17:22
non è che controllino sempre le condizioni...è che ci fanno delle operazioni algebriche

...e come effetto controllano tutte le condizioni se messe in un If...

fero86
30-05-2010, 18:23
& 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 :)

Gremo
30-05-2010, 18:33
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). ;)