Referenz: Vergleich von print und echo von PHP

Lesezeit: 10 Minuten

Was ist der Unterschied zwischen PHPs print und echo?

Stack Overflow hat viele Fragen zu PHPs print und echo Verwendung von Schlüsselwörtern.

Der Zweck dieses Beitrags ist es, eine kanonische Referenzfrage und Antwort zu PHPs bereitzustellen print und echo Schlüsselwörter und vergleichen Sie ihre Unterschiede und Anwendungsfälle.

  • Ich denke, hier ist nicht genug Druck, der Wert zurückzugeben. Print ist nützlich für schnelle Debug-Ausgaben oder ähnliches: strpos($x,$y)!==FALSE OR print “something”. Schnell zu tippen und gut zu lesen. Und “Ist eine Funktion drucken” war aus irgendeinem Grund umständlich zu lesen (Ihre Argumentation scheint … seltsam und nicht offensichtlich) – es ist ein Sprachkonstrukt, es gibt viel Schlimmeres, was Sie damit nicht tun können: variable Funktionen.

    – XzKto

    17. August 2011 um 14:32 Uhr

  • Um dies offen zu halten, muss hier Folgendes getan werden: 1. Aufteilen in eine Frage und eine Antwort. 2. Verweis/Link zu bestehenden Inhalten zum Thema auf Stack Overflow (ähnlich wie hier: stackoverflow.com/questions/3737139/…), aber in der Antwort. 3. Muss CW sein.

    – Kev

    17. August 2011 um 15:08 Uhr

  • Die “Related Column” ist in Ordnung, aber sie ist nicht sehr fokussiert. Um ihren Wert als kanonische Referenzfrage und -antwort zu erhöhen, sollte sie auch gut recherchiert sein, und Links zu anderen spezifischen guten Antworten würden einen Mehrwert schaffen.

    – Kev

    17. August 2011 um 15:37 Uhr

  • Die Frage muss wirklich eine tatsächliche sein Frage. Ich kann ein Banner bezüglich des kanonischen Teils hinzufügen, sobald Sie fertig sind.

    – Tim Post

    19. August 2011 um 15:42 Uhr

Warum zwei Konstrukte?

Die Wahrheit über drucken und Echo liegt darin, dass sie den Benutzern zwar als zwei unterschiedliche Konstrukte erscheinen, aber beide wirklich Schattierungen von Echo sind, wenn Sie sich auf die Grundlagen begeben, dh sich den internen Quellcode ansehen. Dieser Quellcode umfasst sowohl den Parser als auch Opcode-Handler. Betrachten Sie eine einfache Aktion wie das Anzeigen der Zahl Null. Unabhängig davon, ob Sie echo oder print verwenden, wird derselbe Handler “ZEND_ECHO_SPEC_CONST_HANDLER” aufgerufen. Der Handler für print macht eine Sache, bevor er den Handler für echo aufruft, er stellt sicher, dass der Rückgabewert für print 1 ist, wie folgt:

ZVAL_LONG(&EX_T(opline->result.var).tmp_var, 1);

(sehen hier als Referenz)

Der Rückgabewert ist praktisch, wenn man print in einem bedingten Ausdruck verwenden möchte. Warum 1 und nicht 100? Nun, in PHP ist die Wahrhaftigkeit von 1 oder 100 gleich, dh wahr, während 0 in einem booleschen Kontext einem falschen Wert entspricht. In PHP sind alle Nicht-Null-Werte (positiv und negativ) wahre Werte, und dies stammt aus dem Perl-Erbe von PHP.

Aber wenn dies der Fall ist, dann mag man sich fragen, warum echo mehrere Argumente akzeptiert, während print nur eines verarbeiten kann. Für diese Antwort müssen wir uns an den Parser wenden, insbesondere an die Datei zend_language_parser.y. Sie werden feststellen, dass echo die Flexibilität eingebaut hat, dass es einen oder mehrere Ausdrücke drucken kann (siehe Hier). während print darauf beschränkt ist, nur einen Ausdruck zu drucken (siehe dort).

Syntax

In der Programmiersprache C und davon beeinflussten Sprachen wie PHP wird zwischen Anweisungen und Ausdrücken unterschieden. Syntaktisch, echo expr, expr, ... expr ist eine Aussage während print expr ist ein Ausdruck, da er zu einem Wert ausgewertet wird. Daher, wie andere Aussagen, echo expr steht für sich und kann nicht in einen Ausdruck aufgenommen werden:

5 + echo 6;   // syntax error

Im Gegensatz, print exprkann allein eine Aussage treffen:

print 5; // valid

Oder Teil eines Ausdrucks sein:

   $x = (5 + print 5); // 5 
   var_dump( $x );     // 6 

Man könnte versucht sein, daran zu denken print als ob es ein unärer Operator wäre, wie ! oder ~ es ist jedoch kein Operator. Was !, ~ and print Gemeinsam haben sie, dass sie alle in PHP eingebaut sind und jeweils nur ein Argument annehmen. Sie können verwenden print um den folgenden seltsamen, aber gültigen Code zu erstellen:

    <?php 
    print print print print 7; // 7111

Auf den ersten Blick mag das Ergebnis merkwürdig erscheinen, dass die letzte print-Anweisung ihren Operanden ‘7’ ausgibt Erste. Aber wenn Sie tiefer graben und sich die tatsächlichen Opcodes ansehen, macht es Sinn:

line     # *  op                           fetch          ext  return  operands
---------------------------------------------------------------------------------
   3     0  >   PRINT                                            ~0      7
         1      PRINT                                            ~1      ~0
         2      PRINT                                            ~2      ~1
         3      PRINT                                            ~3      ~2
         4      FREE                                                     ~3
         5    > RETURN                                                   1

Der allererste Opcode, der generiert wird, entspricht dem ‘print 7’. ‘~0’ ist eine temporäre Variable, deren Wert 1 ist. Diese Variable wird zu einem Operanden für den nächsten Druck-Opcode, der wiederum eine temporäre Variable zurückgibt und der Prozess wiederholt wird. Die letzte temporäre Variable wird überhaupt nicht verwendet, sie wird freigegeben.

Warum tut print einen Wert zurückgeben und echo nicht?

Ausdrücke werden zu Werten ausgewertet. Zum Beispiel 2 + 3 wertet zu 5und abs(-10) wertet zu 10. Seit print expr selbst ein Ausdruck ist, dann sollte es einen Wert enthalten und das tut es auch, einen konsistenten Wert von 1 gibt ein wahrheitsgemäßes Ergebnis an, und durch Zurückgeben eines Werts ungleich Null wird der Ausdruck für die Aufnahme in einen anderen Ausdruck nützlich. In diesem Snippet ist der Rückgabewert von print beispielsweise nützlich, um eine Funktionssequenz zu bestimmen:

<?php

function bar( $baz ) { 
   // other code   
}
function foo() {
  return print("In and out ...\n");
}

if ( foo() ) {

     bar();
}

Möglicherweise finden Sie print von besonderem Wert, wenn es um spontanes Debuggen geht, wie das nächste Beispiel zeigt:

<?php
$haystack = 'abcde';
$needle="f";
strpos($haystack,$needle) !== FALSE OR print "$needle not in $haystack"; 

// output: f not in abcde

Als Nebenbemerkung sind Aussagen im Allgemeinen keine Ausdrücke; Sie geben keinen Wert zurück. Die Ausnahme bilden natürlich Ausdrucksanweisungen, die print verwenden, und sogar einfache Ausdrücke, die als Anweisung verwendet werden, wie z1;eine Syntax, die PHP von C erbt. Die Ausdrucksanweisung mag seltsam aussehen, ist aber sehr hilfreich, da sie es ermöglicht, Argumente an Funktionen zu übergeben.

Ist print eine Funktion?

Nein, es ist ein Sprachkonstrukt. Während alle Funktionsaufrufe Ausdrücke sind, print (expr) ist ein Ausdruck, obwohl das Bild so aussieht, als würde es Funktionsaufrufsyntax verwenden. In Wahrheit sind diese Klammern eine Klammer-Ausdruck-Syntax, die für die Auswertung von Ausdrücken nützlich ist. Das erklärt die Tatsache, dass sie manchmal optional sind, wenn der Ausdruck einfach ist, wie z print "Hello, world!". Mit einem komplexeren Ausdruck wie z print (5 ** 2 + 6/2); // 28 die Klammern helfen bei der Auswertung des Ausdrucks. Im Gegensatz zu Funktionsnamen print ist syntaktisch ein Schlüsselwortund semantisch a “Sprachkonstrukt”.

Der Begriff „Sprachkonstrukt“ bezieht sich in PHP üblicherweise auf „Pseudo“-Funktionen wie z isset oder empty. Obwohl diese “Konstrukte” genau wie Funktionen aussehen, sind sie es tatsächlich fexprsdas heißt, die Argumente werden ihnen ohne Auswertung übergeben, was eine besondere Behandlung durch den Compiler erfordert. print zufällig ein fexpr ist, das sein Argument auf die gleiche Weise wie eine Funktion auswertet.

Der Unterschied kann durch Drucken gesehen werden get_defined_functions(): es gibt kein print Funktion aufgeführt. (Obwohl printf und Freunde sind: anders printsie sind wahre Funktionen.)

Warum funktioniert dann print(foo)?

Aus dem gleichen Grundecho(foo) funktioniert. Diese Klammern unterscheiden sich stark von Klammern für Funktionsaufrufe, da sie sich stattdessen auf Ausdrücke beziehen. Deshalb darf man codieren echo ( 5 + 8 ) und kann erwarten, dass ein Ergebnis von 13 angezeigt wird (siehe Hinweis). Diese Klammern sind an der Auswertung eines Ausdrucks beteiligt, anstatt eine Funktion aufzurufen. Hinweis: Es gibt andere Verwendungen für Klammern in PHP, wie z. B. if-bedingte Ausdrücke, Zuweisungslisten, Funktionsdeklarationen usw.

Warum machen print(1,2,3) und echo(1,2,3) zu Syntaxfehlern führen?

Die Syntax ist print expr, echo expr oder echo expr, expr, ..., expr. Wenn PHP stößt (1,2,3), versucht es, es als einzelnen Ausdruck zu analysieren und schlägt fehl, weil PHP im Gegensatz zu C keinen wirklichen binären Kommaoperator hat; das Komma dient eher als Trennzeichen. (Sie können dennoch ein binäres Komma in den For-Schleifen von PHP finden, die Syntax wurde von C geerbt.)

Semantik

Die Aussage echo e1, e2, ..., eN; kann als syntaktischer Zucker für verstanden werden echo e1; echo e2; ...; echo eN;.

Da alle Ausdrücke Anweisungen sind, und echo e hat immer die gleichen nebenwirkungen wie print eund der Rückgabewert von print e ignoriert wird, wenn es als Aussage verwendet wird, können wir verstehen echo e als syntaktischer Zucker z print e.

Diese beiden Beobachtungen bedeuten das echo e1, e2, ..., eN; kann als syntaktischer Zucker für angesehen werden print e1; print e2; ... print eN;. (Beachten Sie jedoch die nicht-semantischen Laufzeitunterschiede weiter unten.)

Wir müssen also nur die Semantik für definieren print. print ebei Auswertung:

  1. wertet sein einzelnes Argument aus e und Typumwandlungen den resultierenden Wert in eine Zeichenfolge s. (Daher, print e ist äquivalent zu print (string) e.)
  2. Streamt die Zeichenfolge s zu der Ausgangspuffer (die schließlich zur Standardausgabe gestreamt werden).
  3. Wird als ganze Zahl ausgewertet 1.

Unterschiede auf Bytecode-Ebene

print beinhaltet einen kleinen Overhead beim Füllen der Rückgabevariablen (Pseudocode)

print 125;

PRINT  125,$temp     ; print 125 and place 1 in $temp 
UNSET  $temp         ; remove $temp

Einzel echo kompiliert zu einem Opcode:

echo 125;

ECHO 125

mehrwertig echo kompiliert zu mehreren Opcodes

echo 123, 456;

ECHO 123
ECHO 456

Beachten Sie, dass mehrwertig echo verkettet seine Argumente nicht, sondern gibt sie einzeln aus.

Referenz: zend_do_print, zend_do_echo.

Laufzeitunterschiede

ZEND_PRINT ist wie folgt implementiert (Pseudocode)

PRINT  var, result:

    result = 1
    ECHO var

Also im Grunde genommen 1 in der result-Variablen und delegiert die eigentliche Aufgabe an die ZEND_ECHO Handler. ZEND_ECHO macht folgendes

ECHO var:

    if var is object
        temp = var->toString()
        zend_print_variable(temp)
    else
        zend_print_variable(var)

wo zend_print_variable() führt das eigentliche “Drucken” durch (tatsächlich leitet es lediglich zu einer dedizierten SAPI-Funktion um).

Geschwindigkeit: echo x vs print x

nicht wie Echo, drucken weist eine temporäre Variable zu. Der Zeitaufwand für diese Aktivität ist jedoch winzig, sodass der Unterschied zwischen diesen beiden Sprachkonstrukten vernachlässigbar ist.

Geschwindigkeit: echo a,b,c vs echo a.b.c

Die erste kompiliert sich in drei separate Anweisungen. Die zweite wertet den gesamten Ausdruck aus a.b.c., druckt das Ergebnis und entsorgt es sofort. Da die Verkettung Speicherzuweisungen und Kopieren beinhaltet, ist die erste Option effizienter.

Welche also verwenden?

In Webanwendungen konzentriert sich die Ausgabe meist auf Templates. Da Vorlagen verwenden <?=das ist der Alias ​​von echoscheint es logisch, sich daran zu halten echo auch in anderen Teilen des Codes. echo hat den zusätzlichen Vorteil, dass mehrere Ausdrücke gedruckt werden können, ohne sie zu verketten, und es ist kein Overhead für das Füllen einer temporären Rückgabevariablen erforderlich. Also, verwenden echo.

  • Ich habe dies ausführlich bearbeitet und präzisiert und einen Abschnitt zur Semantik hinzugefügt. Ich bin ziemlich zuversichtlich, aber jemand könnte es noch einmal überprüfen.

    – Jamesfischer

    18. Dezember 2013 um 14:51 Uhr

  • Bedeutet dies dann, dass es besser zu verwenden ist echo $a,$b,$c für die Verkettung von String-Variablen? Ich habe das ehrlich gesagt noch nie im Einsatz gesehen.

    – geoff

    24. Dezember 2013 um 0:19 Uhr

  • Wie wäre es mit einem TL;DR-Abschnitt, der funktionale Unterschiede beschreibt? Wie: print erlaubt nur ein Argument, echo kann mehrere haben; echo kann nicht Teil eines Ausdrucks while sein print kann und kehrt zurück …; und kann eine Leistungszusammenfassung sein. Und all diese „warum“- und „unter der Haube“-Teile danach

    – Jakow L

    5. Mai 2018 um 11:21 Uhr

print kann als Aussage ohne die Notwendigkeit von ; leben, und das ist der Grund, warum wir es in a aufnehmen können $b; print "TRUE": print "FALSE";

964010cookie-checkReferenz: Vergleich von print und echo von PHP

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy