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

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

У переполнения стека много вопросов о PHP print а также echo использование ключевых слов.

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

1 ответ

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

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

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

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

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

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

Синтаксис

В языке программирования 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

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

<?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, они истинные функции.)

Почему 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 на самом деле не имеет двоичного оператора запятой; запятая служит в качестве разделителя. (Тем не менее, вы можете найти двоичную запятую в циклах for PHP, синтаксис которой унаследован от 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 при оценке:

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

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

Скорость: echo a,b,c против echo a.b.c

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

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

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

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

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

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

в то время как

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

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

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

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

print может существовать как утверждение без необходимости;, и это причина, по которой мы можем включить его в $b; print "TRUE": print "FALSE";

Другие вопросы по тегам