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

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

В Stack Overflow есть много вопросов, касающихся использования ключевого слова PHP для print и echo .

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

Solutions Collecting From Web of "Ссылка: сравнение печати и эха PHP"

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

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

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

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

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

Но если это так, то можно задаться вопросом, почему эхо принимает несколько аргументов, тогда как печать может обрабатывать только один. Для этого ответа нам нужно обратиться к парсеру, в частности к файлу 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 

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

print функции?

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

Семантика

Утверждение echo e1, e2, ..., eN; можно понимать как синтаксический сахар для echo e1; echo e2; ...; echo 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 e1; print e2; ... print eN; , (Тем не менее, обратите внимание на не семантические различия во времени выполнения ниже.)

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

  1. оценивает его единственный аргумент e и тип – передает полученное значение в строку s . (Таким образом, print e эквивалентно print (string) e .)
  2. Поток строки s в выходной буфер (который в конечном итоге будет передаваться на стандартный вывод).
  3. Оценивает целое число 1 .

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

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

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

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

 echo 125; ECHO 125 

многозначное 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 в переменную result и делегирует реальную работу обработчику 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

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

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

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

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

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