2015-10-26 17 views
7

Il risultato di:Bug di precedenza dell'operatore PHP?

var_dump(null != $a = 15); 
var_dump($a); 

è:

bool(true) 
int(15) 

Perché questo script non innescando un errore? Dal != (operatore non uguale) ha una precedenza più alta di = (operatore di assegnazione), $a deve essere confrontato prima con null?

+0

decisamente strano. '$ a == null = 15' dà anche dump falsi. E mettere in '(null! = $ A) = 15' sputa un errore' = 'inaspettato. –

+0

Quale alternativa all'interpretazione come 'null! = ($ A = 15)' c'è? Con '(null! = $ A) = 15' proverai ad assegnare il valore 15 ad un valore booleano; quello non funziona – VolkerK

+0

@VolkerK questo è un esempio, questo script non ha uno scopo di vita reale! La mia riflessione inizia con questo tipo di espressione che vedo (e uso) molto 'if (! $ A = foo())'. –

risposta

6

L'unica ragione che posso trovare è che la documentazione dice che questo è ancora legale: http://php.net/manual/en/language.operators.precedence.php#example-129

sembra essere un'eccezione a quanto indicato nella tabella di cui sopra.

+0

Bel colpo su questa piccola nota! –

+3

Penso che un'altra osservazione sia il seguente commento sulla leggibilità: "L'uso delle parentesi, anche quando non strettamente necessario, può spesso aumentare la leggibilità del codice rendendo il raggruppamento esplicito piuttosto che fare affidamento sulla precedenza e sull'associatività degli operatori impliciti." –

+0

Non è una "eccezione intenzionale"; non esiste una regola addizionale del lexer per "permetterlo" esplicitamente. È solo il modo normale in cui funziona. L'esempio nel manuale è solo un promemoria per gli sviluppatori che si chiedono. – VolkerK

2

Questo non riguarda la precedenza degli operatori ma riguarda: gli elenchi di precedenza degli operatori non indicano i dettagli (in realtà, essi non fanno mai), ad es. riguardo le regole del bisonte e la conseguente corrispondenza del modello e riduzione dello stack.
Prendiamo la dichiarazione null != $a = 15;, per semplicità senza var_dump.
Questo è il modo in cui il parser "vede" questa affermazione - oppure: vede che lo è una dichiarazione.
(spero che questo sarà reso con un carattere fisso-larghezza ovunque ...)

null      !=     $a         = 15       ; 
               T_VARIABLE       
identifier          compound_variable      T_LNUMBER 
namespace_name         reference_variable      common_scalar 
general_constant         base_variable       scalar 
scalar           base_variable_with_functions_calls  expr_without_variable 
expr_without_variable       variable       = expr 
expr      T_IS_NOT_EQUAL    \______ expr_without_variable _________/ 
    \__________________ expr ____________________________________________/           ; 
          \_________________  unticked_statement _______________________________________________/ 
                statement         

(È possibile cercare le regole a https://github.com/php/php-src/blob/PHP-5.6.15/Zend/zend_language_parser.y)

Non esiste una regola speciale per l'operatore di assegnamento in questo caso; semplicemente non esiste un altro modo per far sì che il parser corrisponda all'istruzione, quindi la precedenza non si applica.