Ссылка: сравнение PHP-печати и эха

В чем разница между PHP print и echo?

У много вопросов, связанных с использованием PHP print и echo.

Цель этого сообщения - предоставить канонический reference вопрос и ответ о ключевых словах PHP print и echo и сравнить их различия и использовать- случаев.

Ответ 1

Почему две конструкции?

Истина о печати и эхо заключается в том, что, хотя они кажутся пользователям как две разные конструкции, они оба являются действительно оттенками эха, если вы переходите к основам, то есть смотрите внутренний код. Этот исходный код включает в себя синтаксический анализатор, а также обработчики кода операций. Рассмотрим простое действие, такое как отображение нулевого числа. Будь вы используете эхо или печать, вызывается тот же обработчик "ZEND_ECHO_SPEC_CONST_HANDLER". Обработчик для печати делает одно, прежде чем он вызывает обработчик для эха, он гарантирует, что возвращаемое значение для печати равно 1:

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

(см. здесь для справки)

Возвращаемое значение - это удобство, если вы хотите использовать печать в условном выражении. Почему 1, а не 100? Ну, в PHP правдоподобие 1 или 100 одинаково, т.е. True, тогда как 0 в булевом контексте приравнивается как ложное значение. В PHP все ненулевые значения (положительные и отрицательные) являются истинными значениями, и это происходит из наследия PHP Perl.

Но если это так, то можно задаться вопросом, почему эхо принимает несколько аргументов, тогда как печать может обрабатывать только один. Для этого ответа нам нужно обратиться к парсеру, в частности к файлу zend_language_parser.y. Вы заметите, что эхо имеет гибкость, встроенную для печати одного или нескольких выражений (см. здесь). в то время как печать ограничена печатью только одного выражения (см. там).

Синтаксис

В языке программирования C и языках, на которые он влияет, например, на PHP, существует различие между операторами и выражениями. Синтаксически echo expr, expr, ... expr является выражением, а print expr является выражением, так как оно оценивает значение. Поэтому, как и другие утверждения, echo expr стоит сам по себе и не может быть включен в выражение:

5 + echo 6;   // syntax error

Напротив, print expr, может самостоятельно выражать утверждение:

print 5; // valid

Или, быть частью выражения:

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

Можно подумать о print, как если бы это был унарный оператор, например ! или ~, но он не является оператором. Что общего !, ~ and print заключается в том, что все они встроены в PHP, и каждый принимает только один аргумент. Вы можете использовать print для создания следующего странного, но действительного кода:

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

На первый взгляд результат может показаться странным, что последний оператор печати сначала печатает свой операнд "7". Но, если вы копаете глубже и смотрите на фактические коды операций, это имеет смысл:

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

Самый первый код операции, который генерируется, соответствует тому, что соответствует "print 7". "~ 0" - временная переменная, значение которой равно 1. Эта переменная становится и операндом для следующего кода операции печати, который, в свою очередь, возвращает временную переменную, и процесс повторяется. Последняя временная переменная не используется вообще, поэтому она освобождается.

Почему print возвращает значение, а echo - нет?

Выражения оценивают значения. Например, 2 + 3 имеет значение 5, а abs(-10) - 10. Так как print expr само является выражением, то оно должно содержать значение, и оно делает, согласованное значение 1 указывает на правдивый результат и, возвращая ненулевое значение, выражение становится полезным для включения в другое выражение. Например, в этом фрагменте возвращаемое значение печати полезно при определении последовательности функций:

<?php

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

if ( foo() ) {

     bar();
}

Вы можете найти распечатку определенного значения, когда дело доходит до отладки "на лету", как показано в следующем примере:

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

// output: f not in abcde

В качестве примечания, как правило, утверждения не являются выражениями; они не возвращают значение. Исключением, конечно, являются выражения, которые используют выражения print и даже простые выражения, используемые в качестве инструкции, такие как 1;, синтаксис, который PHP наследует от C. Выражение выражения может выглядеть странно, но это очень полезно, передать аргументы в функции.

Является ли print функцией?

Нет, это языковая конструкция. Хотя все вызовы функций являются выражениями, print (expr) является выражением, несмотря на визуальное представление, которое выглядит так, как если бы оно использовало синтаксис вызова функции. По правде говоря, эти скобки являются скобками-синтаксисом expr, полезными для оценки выражения. Это объясняет тот факт, что порой они являются необязательными, если выражение является простым, например print "Hello, world!". С более сложным выражением, таким как print (5 ** 2 + 6/2); // 28, скобки помогают оценить выражение. В отличие от имен функций print синтаксически ключевое слово, и семантически "языковая конструкция" .

Термин "языковая конструкция" в PHP обычно относится к "псевдо" функциям типа isset или empty. Хотя эти "конструкции" выглядят точно так же, как функции, они фактически fexprs, то есть аргументы передаются им без оценки, что требует специальных лечение от компилятора. print оказывается fexpr, который решает оценить его аргумент так же, как функция.

Разницу можно увидеть при печати get_defined_functions(): нет функции print. (Хотя printf и друзья: в отличие от print, они являются истинными функциями.)

Почему печать (foo) работает?

По той же причине, что работает echo(foo). Эти круглые скобки сильно отличаются от круглых скобок вызова функций, поскольку они относятся к выражениям. Вот почему можно запрограммировать echo ( 5 + 8 ) и ожидать, что будет отображаться результат 13 (см. ссылка). Эти скобки участвуют в оценке выражения, а не при вызове функции. Примечание. Существуют другие варианты использования скобок в PHP, например if-условные выражения, списки назначений, объявления функций и т.д.

Почему print(1,2,3) и echo(1,2,3) приводят к синтаксическим ошибкам?

Синтаксис print expr, echo expr или echo expr, expr, ..., expr. Когда PHP встречается с (1,2,3), он пытается разобрать его как одно выражение и терпит неудачу, потому что в отличие от C PHP не имеет бинарного оператора запятой; запятая больше служит разделителем. (Вы можете найти двоичную запятую, тем не менее, в PHP for-loops, синтаксис, который он унаследовал от C.)

Семантика

Заявление echo e1, e2, ..., eN; можно понимать как синтаксический сахар для echo e1; echo e2; ...; echo eN;.

Поскольку все выражения являются операторами, а echo e всегда имеет те же побочные эффекты, что и print e, а возвращаемое значение print e игнорируется при использовании в качестве инструкции, мы можем понимать echo e как синтаксический сахар для print e.

Эти два наблюдения означают, что echo e1, e2, ..., eN; можно рассматривать как синтаксический сахар для print e1; print e2; ... print eN;. (Однако обратите внимание на различия, не связанные с семантической средой выполнения.)

Поэтому нам нужно определить семантику для print. print e, когда оценивается:

  • оценивает свой единственный аргумент e и type-casts полученное значение для строки s. (Таким образом, print e эквивалентно print (string) e.)
  • Поток строки s в выходной буфер (который в конечном итоге будет передан на стандартный вывод).
  • Вычисляет целое число 1.

Различия на уровне байт-кода

print включает небольшие накладные расходы при заполнении возвращаемой переменной (псевдокод)

print 125;

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

single echo компилируется в один код операции:

echo 125;

ECHO 125

multi-value echo компилируется в несколько кодов операций

echo 123, 456;

ECHO 123
ECHO 456

Обратите внимание, что многозначное значение echo не объединяет его аргументы, а выводит их по очереди.

Ссылка: zend_do_print, zend_do_echo.

Разница во времени

ZEND_PRINT реализуется следующим образом (псевдокод)

PRINT  var, result:

    result = 1
    ECHO var

Поэтому он в основном помещает 1 в переменную результата и делегирует реальное задание обработчику ZEND_ECHO. ZEND_ECHO выполняет следующие

ECHO var:

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

где zend_print_variable() выполняет фактическую "печать" (фактически, она просто перенаправляется на выделенную функцию SAPI).

Скорость: echo x vs print x

В отличие от эха, print выделяет временную переменную. Однако количество времени, затрачиваемого на эту деятельность, незначительно, поэтому разница между этими двумя языковыми конструкциями ничтожно мала.

Скорость: echo a,b,c vs echo a.b.c

Первый объединяет до трех отдельных операторов. Второе оценивает все выражение a.b.c., печатает результат и немедленно его удаляет. Поскольку конкатенация включает в себя распределение памяти и копирование, первый вариант будет более эффективным.

Итак, какой из них использовать?

В веб-приложениях вывод главным образом сосредоточен в шаблонах. Поскольку в шаблонах используется <?=, который является псевдонимом echo, логично придерживаться echo в других частях кода. echo имеет дополнительное преимущество, заключающееся в возможности печати нескольких выражений без их конкатенации и не требует накладных расходов на заполнение временной возвращаемой переменной. Итак, используйте echo.

Ответ 2

Я знаю, что опоздал, но я хотел бы добавить, что в моем коде

 $stmt = mysqli_stmt_init($connection) or echo "error at init"; 

выдает ошибку "синтаксическая ошибка, неожиданное" эхо "(T_ECHO)"

в то время как

 $stmt = mysqli_stmt_init($connection) or print "error at init";

работает отлично.

Документы о эхе говорят "эхо ( в отличии от некоторых других языковых конструкций) не ведет себя как функция" здесь, но о печати документах также говорит, "печать не на самом деле реальная функция (это конструкция языка)" здесь. Поэтому я не уверен, почему. В документах echo и print также говорится: "Основные отличия echo в том, что print принимает только один аргумент и всегда возвращает 1". Вот

Я был бы счастлив, если бы кто-нибудь мог пролить свет на это поведение.