'AND' vs '&&' como operador


298

Eu tenho uma base de código onde os desenvolvedores decidiram usar ANDe em ORvez de &&e ||.

Eu sei que há uma diferença na precedência dos operadores ( &&vai antes and), mas com a estrutura fornecida ( PrestaShop para ser preciso) claramente não é uma razão.

Qual versão você está usando? É andmais legível do que &&? Ou não há diferença?


1
Observe que ~é o operador NOT bit a bit e não o lógico. ;-)
Gumbo

2
Sim eu conheço. Maus hábitos :) . É um pouco estranho que no PHP existam 'e', ​​'ou' e 'xor', mas não há 'não', não é?
ts.

1
@ts: a resposta correta aqui é o fornecido pela R. Bemrose stackoverflow.com/questions/2803321/and-vs-as-operator/...
Marco Demaio

4
! é o operador lógico não
Razor Storm

2
@chiliNUT muito bem. Na época, deve ter feito sentido. Parece que a resposta errada à espreita foi punido neste momento :)
doublejosh

Respostas:


664

Se você usar ANDe OR, eventualmente, será enganado por algo assim:

$this_one = true;
$that = false;

$truthiness = $this_one and $that;

Quer adivinhar o que $truthinessé igual?

Se você disse false... bzzzt, desculpe, errado!

$truthinessacima tem o valor true. Por quê? =tem uma precedência mais alta que and. A adição de parênteses para mostrar a ordem implícita torna isso mais claro:

($truthiness = $this_one) and $that

Se você usasse no &&lugar do andprimeiro exemplo de código, ele funcionaria como esperado e estará false.

Conforme discutido nos comentários abaixo, isso também funciona para obter o valor correto, pois os parênteses têm maior precedência do que =:

$truthiness = ($this_one and $that)

135
+1: isso deve ser esclarecido na documentação do PHP ou o PHP deve mudar e dar a mesma precedência a esses operadores ou DEPRECATE de and oruma vez por todas. Vi muitas pessoas pensando que são exatamente a mesma coisa e as respostas aqui são mais depoimentos.
Marco Demaio

11
Na verdade, outras linguagens (por exemplo, Perl e Ruby) também têm essas variantes com a mesma distinção de precedência, portanto não seria sensato desviar-se desse padrão (por mais intrigante que possa ser para iniciantes), tornando a precedência igual em PHP. Sem mencionar a compatibilidade com versões anteriores de toneladas de aplicativos PHP.
Mladen Jablanović

23
A incapacidade das pessoas de ler a documentação de um idioma não toma as decisões erradas. Como observa Mladen, Perl e Ruby também usam esses operadores extras e com as mesmas precedências. Ele permite construções como $foo and bar(), que são bons atalhos para instruções if. Se o comportamento inesperado (devido a documentação incorreta ou não a leitura) fosse um motivo para não usar algo que não estaríamos falando sobre o uso do PHP.
Altreus 30/08/12

2
Passei 3 minutos para encontrar linha errada: $ this = true , :( eo que cerca de US $ truthiness = ($ this e US $ disso); aparência é melhor para mim :)
Dmitriy Kozmenko

6
Concordo com Dmitriy - colocar a avaliação booleana entre parênteses ajuda a esclarecer a intenção do código. Eu acho que o operador e sua função, como eles existem agora, são valiosos e consistentes com outras linguagens, é o trabalho do programador entender a linguagem.
Jon z

43

Dependendo de como está sendo usado, pode ser necessário e até útil. http://php.net/manual/en/language.operators.logical.php

// "||" has a greater precedence than "or"

// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;

// The constant false is assigned to $f and then true is ignored
// Acts like: (($f = false) or true)
$f = false or true;

Mas na maioria dos casos, parece mais um gosto do desenvolvedor, como todas as ocorrências disso que eu já vi no framework CodeIgniter, como o @Sarfraz mencionou.


2
Vale a pena notar que o "verdadeiro" não é ignorado se essa expressão fizer parte de uma declaração maior. Considere o caso if ($f = false or true) $f = true;- o resultado seria que $fse torne verdadeiro no final, porque a expressão é avaliada como verdadeira em geral.
22312 Chris Browne

1
não, você simplesmente substituiu a variável mais tarde. a expressão ainda é avaliada como falsa, então você a substitui por true na próxima linha.
R3wt

2
Na verdade, ele estava certo. Primeiro, $fé atribuído false - mas a condição é avaliada como true, então $fé substituída. Se a condição $ffosse avaliada como falsa, nunca seria substituída de qualquer maneira.
ahouse101

É ridículo sugerir que os desenvolvedores sigam seu próprio gosto. Esqueça o pesadelo de outro desenvolvedor tentando manter o mesmo código, o desenvolvedor que escreveu o código em si seria cometer erros semânticos em qualquer código escrito porque ele / ela prefere andmais &&, onde andfunciona como esperado apenas em algumas situações e &&funciona como esperado em todos situações.
ADTC

13

Por questões de segurança, sempre coloco parênteses em minhas comparações e as espaço. Dessa forma, não preciso confiar na precedência do operador:

if( 
    ((i==0) && (b==2)) 
    || 
    ((c==3) && !(f==5)) 
  )

29
Pessoalmente, acho que adicionar parênteses desnecessários extras torna a leitura mais confusa do que ter apenas o que você precisa. Por exemplo, acho que isso é muito mais fácil de ler: if (($ i == 0 && $ b == 2) || ($ c == 3 && $ f! = 5))
rooby

4
Eu acho que esse é o código mais bonito que eu já vi o dia todo. Bom trabalho.
Rm-vanda

Como o PHP é uma linguagem interpretada, ele será executado rapidamente se você não usar espaços em branco desnecessários ou novas linhas no seu código. Se você fizer o mesmo em uma linguagem compilada, levará apenas mais tempo para compilar, mas não terá efeito no tempo de execução. Não quero dizer que fazê-lo uma vez marcará a diferença, mas em um aplicativo inteiro usando php + javascript ambos escreveram como o exemplo ... os tempos de carregamento serão maiores, com certeza. Explicação: Espaços em branco e novas linhas são ignoradas, mas para ignorá-las, elas precisam ser verificadas. Isso acontece no tempo de execução em idiomas interpretados e ao compilar em idiomas compilados.
JoelBonetR:

@JoelBonetR, se você estiver usando php opcache ou semelhante, sua preocupação com o tempo de carregamento é irrelevante. Eu espero que ninguém esteja executando um site php de produção sem ele ...
PeloNZ

@PeloNZ para que você possa escrever sujo, porque ele será armazenado em cache de qualquer maneira e todo o projeto levará apenas um segundo a carregar ao atualizar, não é? Codificar limpo é para você e seus colegas de equipe, preocupar-se com os horários era apenas um ponto que a maioria das pessoas ignorava ou simplesmente não sabia.
JoelBonetR

11

A precedência difere entre && e e (&& tem maior precedência que e), algo que causa confusão quando combinado com um operador ternário. Por exemplo,

$predA && $predB ? "foo" : "bar"

retornará uma string enquanto

$predA and $predB ? "foo" : "bar"

retornará um booleano .


10

Como andtem precedência menor do que =você pode usá-lo na atribuição de condições:

if ($var = true && false) // Compare true with false and assign to $var
if ($var = true and false) // Assign true to $var and compare $var to false

2

Deixe-me explicar a diferença entre "e" - "&&" - "&".

"&&" e "e" são operações AND lógicas e fazem a mesma coisa, mas a precedência do operador é diferente.

A precedência (prioridade) de um operador especifica quão "firmemente" ele liga duas expressões. Por exemplo, na expressão 1 + 5 * 3, a resposta é 16 e não 18 porque o operador de multiplicação ("*") tem uma precedência mais alta que o operador de adição ("+").

Misturá-los juntos em uma única operação, pode dar resultados inesperados em alguns casos, eu recomendo sempre usar &&, mas essa é a sua escolha.


Por outro lado, "&" é uma operação AND bit a bit . É usado para a avaliação e manipulação de bits específicos dentro do valor inteiro.

Exemplo: se você fizer (14 e 7), o resultado será 6.

7   = 0111
14  = 1110
------------
    = 0110 == 6

1

Qual versão você está usando?

Se os padrões de codificação para a base de código específica para a qual estou escrevendo o código especificar qual operador deve ser usado, eu definitivamente o utilizarei. Caso contrário, e o código determina qual deve ser usado (não frequentemente, pode ser facilmente contornado), então usarei isso. Caso contrário, provavelmente && .

É 'e' mais legível que '&&'?

É mais legível para você . A resposta é sim e não, dependendo de muitos fatores, incluindo o código em torno do operador e, de fato, a pessoa que o lê!

|| há ~ diferença?

Sim. Consulte operadores lógicos para ||e operadores bit a bit para ~.


0

Eu acho que é uma questão de gosto, embora (erroneamente) misturá-las possa causar alguns comportamentos indesejados:

true && false || false; // returns false

true and false || false; // returns true

Portanto, usando && e || é mais seguro, pois eles têm a maior precedência. No que diz respeito à legibilidade, eu diria que esses operadores são universais o suficiente.

ATUALIZAÇÃO : Sobre os comentários dizendo que ambas as operações retornam falsas ... bem, na verdade o código acima não retorna nada, desculpe-me pela ambiguidade. Para esclarecer: o comportamento no segundo caso depende de como o resultado da operação é usado. Observe como a precedência dos operadores entra em jogo aqui:

var_dump(true and false || false); // bool(false)

$a = true and false || false; var_dump($a); // bool(true)

O motivo $a === trueé que o operador de atribuição tem precedência sobre qualquer operador lógico, como já foi muito bem explicado em outras respostas.


16
Isso não é verdade, todos eles retornam falsos.
Jay

0

Aqui está um pequeno exemplo de contador:

$a = true;
$b = true;
$c = $a & $b;
var_dump(true === $c);

resultado:

bool(false)

Eu diria que esse tipo de erro de digitação tem muito mais probabilidade de causar problemas insidiosos (da mesma maneira que =vs ==) e tem muito menos probabilidade de ser notado do que adn/ rotypo, que sinalizará como erros de sintaxe. Também acho e / ou é muito mais fácil de ler. FWIW, a maioria das estruturas PHP que expressam uma preferência (a maioria não) especifica e / ou. Eu também nunca me deparei com um caso real, não artificial, em que isso teria importância.


0

Outro bom exemplo usando ifinstruções sem =operações de atribuição.

if (true || true && false); // is the same as:
if (true || (true && false)); // TRUE

e

if (true || true AND false); // is the same as:
if ((true || true) && false); // FALSE

porque ANDtem uma precedência mais baixa e, portanto, ||uma precedência mais alta.

Estes são diferentes nos casos de true, false, falsee true, true, false. Veja https://ideone.com/lsqovs para um exemplo elaborado.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.