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
È stato utile?

Soluzione

Dennis Ritchie risponde

  

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:

Commento di Volte :

(!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 ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top