Pergunta

& tem &&. | tem ||. Por que não ^ Tem ^^?

Eu entendo que não seria curto-circuito, mas teria semântica diferente. Em C, true é realmente qualquer valor diferente de zero. Bit a bit XOR nem sempre é a mesma coisa que XOR lógico:

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)

Desde que você não pode sempre contar com um valor verdadeiro ser 1 ou -1, não seria um operador de ^^ ser muito útil? Eu sempre tenho que fazer coisas estranhas como esta:

if(!!a ^ !!b) // looks strange
Foi útil?

Solução

Dennis Ritchie responde

Existem duas razões históricas e práticas pelas quais existe nenhum operador ^^.

A prática é: não há muito uso para o operador. O principal ponto de && e || é tirar proveito de sua avaliação de curto-circuito, não só por razões de eficiência, mas mais frequentemente para a expressividade e correção.
[...]
Por outro lado, um operador ^^ sempre forçar a avaliação de ambos os ramos da expressão, então não há ganho de eficiência. Além disso, situações em que ^^ é realmente chamado para são muito raros, embora exemplos podem ser criados. Estas situações obter mais raro e estranho como você empilhar o operator--

if (cond1() ^^ cond2() ^^ cond3() ^^ ...) ...

faz o consequente exatamente quando um número ímpar dos condx()s são verdadeiras. Em contraste, os && e || análogos permanecem bastante plausível e útil.

Outras dicas

Tecnicamente, já existe:

a != b

Uma vez que este irá avaliar como true se o valor de verdade dos operandos são diferentes.

Editar:

Volte 's comentário:

(!a) != (!b)

é correto porque a minha resposta acima não funciona para tipos int. Vou apagar meu se acrescenta a sua resposta.

Editar novamente:

Talvez eu estou esquecendo alguma coisa de C ++, mas quanto mais eu penso sobre isso, mais eu me pergunto por que você faria if (1 ^ 2) nunca escrever em primeiro lugar. A finalidade para ^ é exclusivo-ou dois números juntos (que avalia para outro número), não convertê-los para valores booleanos e comparar os seus valores de verdade.

Isto parece que seria uma suposição estranho para um designer de linguagem para fazer.

Para operandos não-bool, eu acho que o que você quer é para a ^^ b a ser avaliado como:

(a != 0) ^ (b != 0)

Bem, você tem a opção acima e você tem algumas opções listadas em outras respostas.

O ^^ operador seria redundante para operandos bool. Falando apenas sobre operandos booleanos, por causa do argumento, vamos fingir que ^ era bit a bit-only e que ^^ existia como uma lógica XOR. Então você tem as seguintes opções:

  • & - Bitwise E - sempre avalia ambos operandos
  • && - E lógico - nem sempre avaliar tanto operandos
  • | - OR bit a bit - sempre avalia ambos operandos
  • || - Lógico OR - nem sempre avaliar tanto operandos
  • ^ - XOR bit a bit - sempre deve avaliar tanto operandos
  • ^^ - XOR Lógico - sempre deve avaliar tanto operandos

Por que não criar ^^ essencialmente converter valores numéricos em bools e então agir como ^? Esta é uma boa pergunta. Talvez porque é mais potencialmente confusa do que && e ||, talvez porque você pode facilmente construir o equivalente a ^^ com outros operadores.

Eu não posso dizer o que estava na cabeça de Kernighan e Ritchie quando inventaram C, mas você fez uma breve referência a "não seria um curto-circuito", e eu estou supondo que é a razão: Não é possível aplicá-la de forma consistente. Você pode XOR não curto-circuito como você pode AND e OR, então ^^ não poderia totalmente paralelo && e ||. Assim, os autores poderiam muito bem ter decidido que fazer uma operação que tipo de tipo de olhares como seu paralelo aos outros, mas não é bem seria pior do que não tê-lo em tudo.

Pessoalmente, a principal razão de eu usar && e || é para o curto-circuito, em vez do não-bit a bit. Na verdade, eu muito raramente usar os operadores bit a bit em tudo.

Outra solução para aqueles postados acima (mesmo que se exige um outro ramo no código) seria:

if ( (a? !b : b ) )

que é equivalente a xor.

operador

Em Java do ^ aliás, faz fazer XOR lógico quando usado em dois operandos booleanos (assim como & e | em Java fazer não curto-circuito lógico AND e OR, respectivamente, quando aplicado a booleans). A principal diferença com C / C ++ é que C / C ++ permite que você misturar inteiros e lógicos, enquanto que Java não.

Mas eu acho que é má prática para usar inteiros como booleans de qualquer maneira. Se você quer fazer operações lógicas, você deve furar a qualquer valores bool, ou inteiros que são 0 ou 1. Então ^ funciona bem como XOR lógico.

Uma questão análoga seria perguntar, como você faria não curto-circuito lógico AND e OR em C / C ++? A resposta usual é usar os operadores & e | respectivamente. Mas, novamente, isso depende dos valores sendo bool ou 0 ou 1. Se você permitir que quaisquer valores inteiros, então isso não quer trabalhar.

Independentemente do caso a favor ou contra ^^ como um operador, você exemplo, com strcmp() suga. Ela não retorna um valor de verdade (verdadeiro ou falso), ele retorna uma relação entre suas entradas, codificado como um inteiro.

Claro, qualquer inteiro pode ser interpretado como um valor de verdade em C, caso em que 0 é "falso" e todos os outros valores são "verdadeiros", mas que é o oposto do que strcmp() retornos.

Seu exemplo deve começar:

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"

Você deve comparar o valor de retorno com 0 a convertê-lo para um valor booleano adequada indicando se as cordas eram iguais ou não.

Com booleans "bom", representada canonicamente como 0 ou 1, o operador bit a bit ^ funciona muito melhor, também ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top