Perché non esiste un operatore ^^ in C / C ++?
-
10-07-2019 - |
Domanda
& amp;
ha & amp; & amp;
. |
ha ||
. Perché ^
non ha ^^
?
Capisco che non sarebbe un corto circuito, ma avrebbe una semantica diversa. In C, true
è in realtà qualsiasi valore diverso da zero. XOR bit a bit non è sempre la stessa cosa di XOR logico:
int a=strcmp(str1,str2);// evaluates to 1, which is "true"
int b=strcmp(str1,str3);// evaluates to 2, which is also "true"
int c=a ^^ b; // this would be false, since true ^ true = false
int d=a ^ b; //oops, this is true again, it is 3 (^ is bitwise)
Dato che non puoi sempre fare affidamento su un valore vero che è 1
o -1
, un operatore ^^
non sarebbe molto utile? Spesso devo fare cose strane come questa:
if(!!a ^ !!b) // looks strange
Soluzione
Vi sono ragioni sia storiche che pratiche per cui non esiste un operatore
^^
.La pratica è: non c'è molto uso per l'operatore. Il punto principale di
& amp; & amp;
e||
è sfruttare la loro valutazione del corto circuito non solo per motivi di efficienza, ma più spesso per espressività e correttezza. < br> [...]
Al contrario, un operatore^^
forzerebbe sempre la valutazione di entrambi i rami dell'espressione, quindi non c'è guadagno di efficienza. Inoltre, le situazioni in cui^^
sono veramente richieste sono piuttosto rare, anche se è possibile creare esempi. Queste situazioni diventano più rare e più strane quando si accumula l'operatore ...if (cond1() ^^ cond2() ^^ cond3() ^^ ...) ...
fa il risultato esattamente quando un numero dispari di
condx ()
è vero. Al contrario, gli analoghi& amp; & amp;
e||
rimangono abbastanza plausibili e utili.
Altri suggerimenti
Tecnicamente, ne esiste già uno:
a != b
poiché ciò valuterà vero se il valore di verità degli operandi differisce.
Modifica:
(!a) != (!b)
è corretto perché la mia risposta sopra non funziona per i tipi int
. Eliminerò la mia se aggiunge la sua risposta.
Modifica di nuovo:
Forse sto dimenticando qualcosa del C ++, ma più ci penso, più mi chiedo perché dovresti mai scrivere if (1 ^ 2)
in primo luogo. Lo scopo di ^
è quello di esclusivi o due numeri insieme (che valuta un altro numero), non convertirli in valori booleani e confrontare i loro valori di verità.
Sembra che sarebbe una strana ipotesi per un designer linguistico fare
Per operandi non bool
, immagino che ciò che vorresti fosse che a ^^ b
fosse valutato come:
(a != 0) ^ (b != 0)
Bene, hai l'opzione sopra e hai alcune opzioni elencate in altre risposte.
L'operatore ^^
sarebbe ridondante per gli operandi bool
. Parlando solo di operandi booleani, per ragioni di argomento, facciamo finta che ^
fosse solo bit a bit e che ^^
esistesse come XOR logico. Hai quindi queste opzioni:
-
& amp;
- Bitwise AND - valuta sempre entrambi gli operandi -
& amp; & amp;
- AND logico - non valuta sempre entrambi gli operandi -
|
- Bitwise OR - valuta sempre entrambi gli operandi -
||
- OR logico - non valuta sempre entrambi gli operandi -
^
- Bitwise XOR - deve sempre valutare entrambi gli operandi -
^^
- XOR logico - deve sempre valutare entrambi gli operandi
Perché non hanno creato ^^
per convertire essenzialmente valori numerici in bool
e quindi agire come ^
? Questa è una buona domanda. Forse perché è potenzialmente più confuso di & amp; & amp;
e ||
, forse perché puoi facilmente costruire l'equivalente di ^^
con altri operatori .
Non posso dire cosa ci fosse in testa a Kernighan e Ritchie quando inventarono C, ma tu hai fatto un breve riferimento a "non sarebbe un corto circuito", e immagino che sia la ragione: è non è possibile implementarlo in modo coerente. Non puoi cortocircuitare XOR come puoi AND e OR, quindi ^^ non potrebbe essere completamente parallelo & amp; & amp; e || Quindi gli autori potrebbero aver deciso che fare un'operazione di quel tipo di simile sembra parallela alle altre ma che non è del tutto sarebbe peggio che non averla affatto.
Personalmente, il motivo principale per cui utilizzo & amp; & amp; e || è per il cortocircuito piuttosto che per non bit-bit. In realtà uso molto raramente gli operatori bit per bit.
Un'altra soluzione alternativa a quelle pubblicate sopra (anche se richiede un altro ramo nel codice) sarebbe:
if ( (a? !b : b ) )
che equivale a xor.
In Java l'operatore ^
esegue effettivamente XOR logico quando viene utilizzato su due operandi booleani (proprio come & amp;
e |
in Java fanno AND e OR logici non in corto circuito, rispettivamente, quando applicati a valori booleani). La differenza principale con C / C ++ è che C / C ++ consente di mescolare numeri interi e valori booleani, mentre Java no.
Ma penso che sia una cattiva pratica usare numeri interi come booleani. Se si desidera eseguire operazioni logiche, è necessario attenersi ai valori bool
o ai numeri interi che sono 0 o 1. Quindi ^
funziona perfettamente come XOR logico.
Una domanda analoga sarebbe quella di porre, come faresti AND AND OR logici non in corto circuito in C / C ++? La solita risposta è usare rispettivamente gli operatori & amp;
e |
. Ma ancora una volta, questo dipende dal fatto che i valori sono bool
o 0 o 1. Se si consentono valori interi, anche questo non funziona.
Indipendentemente dal caso a favore o contro ^^
come operatore, ad esempio con strcmp ()
fa schifo. Non restituisce un valore di verità (vero o falso), restituisce una relazione tra i suoi input, codificata come numero intero.
Certo, qualsiasi numero intero può essere interpretato come un valore di verità in C, nel qual caso 0 è "falso". e tutti gli altri valori sono " true " ;, ma questo è l'opposto di ciò che strcmp ()
restituisce.
Il tuo esempio dovrebbe iniziare:
int a = strcmp(str1, str2) == 0; // evaluates to 0, which is "false"
int b = strcmp(str1, str3) == 0; // evaluates to 0, which is also "false"
Devi confrontare il valore restituito con 0 per convertirlo in un valore booleano appropriato che indica se le stringhe erano uguali o meno.
Con " corretto " booleani, rappresentato canonicamente come 0 o 1, anche l'operatore bit per bit ^
funziona molto meglio ...