PHP的print和echo有什么区别?

发布于 2024-11-30 10:28:23 字数 338 浏览 0 评论 0原文

PHP 的 printecho 有什么区别?

Stack Overflow 有许多关于 PHP 的 printecho 关键字用法的问题。

这篇文章的目的是提供一个规范的参考问题并回答 PHP 的 printecho 关键字,并比较它们的差异和用例。

What is the difference between PHP's print and echo?

Stack Overflow has many questions asking about PHP's print and echo keyword usage.

The purpose of this post is to provide a canonical reference question and answer about PHP's print and echo keywords and compare their differences and use-cases.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

⒈起吃苦の倖褔 2024-12-07 10:28:23

为什么有两个构造?

printecho 的真相是,虽然它们对用户来说是两种不同的结构,但如果您深入了解基础知识,即查看内部源代码。该源代码涉及解析器以及操作码处理程序。考虑一个简单的操作,例如显示数字零。无论您使用 echo 还是 print,都会调用相同的处理程序“ ZEND_ECHO_SPEC_CONST_HANDLER”。 print 的处理程序在调用 echo 的处理程序之前做了一件事,它确保 print 的返回值为 1,如下所示:(

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

请参阅 此处供参考)

如果希望在条件表达式中使用 print,则返回值会很方便。为什么是 1 而不是 100?在 PHP 中,1 或 100 的真实性是相同的,即 true,而布尔上下文中的 0 等同于 false 值。在 PHP 中,所有非零值(正值和负值)都是真值,这源自 PHP 的 Perl 遗产。

但是,如果是这种情况,那么人们可能会想知道为什么 echo 需要多个参数,而 print 只能处理一个参数。为了得到这个答案,我们需要求助于解析器,特别是文件zend_language_parser.y。您会注意到 echo 具有内置的灵活性,因此它可以打印一个或多个表达式(请参阅 此处)。而 print 仅限于打印一个表达式(请参阅那里) 。

语法

在 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 视为一元运算符,例如 !~,但事实并非如此一个操作员。 !、~ 和 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 计算结果为 5abs(-10) 计算结果为 10。由于 print expr 本身就是一个表达式,因此它应该保存一个值,并且确实如此,一致的值 1 表示结果为真,并且通过返回非零值来表示表达式对于包含在另一个表达式中变得有用。例如,在此代码片段中, print 的返回值对于确定函数序列很有用:

<?php

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

if ( foo() ) {

     bar();
}

当涉及到动态调试时,您可能会发现 print 具有特定值,如下例所示:

<?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) 是一个表达式,尽管看起来好像在使用函数调用语法。事实上,这些括号是括号表达式语法,对于表达式求值很有用。这就解释了这样一个事实:如果表达式很简单,例如 print "Hello, world!",有时它们是可选的。使用更复杂的表达式,例如 print (5 ** 2 + 6/2); // 28 括号有助于表达式的求值。与函数名称不同,print 在语法上是一个关键字,并且在语义上是“语言构造”

PHP 中的术语“语言构造”通常指“伪”函数,例如 issetempty。虽然这些“构造”看起来和函数一模一样,但它们实际上是 fexprs,也就是说,参数是传递给它们而不进行评估,这需要编译器的特殊处理。 print 恰好是一个 fexpr,它选择以与函数相同的方式计算其参数。

通过打印 get_define_functions() 可以看出差异:没有列出 print 函数。 (尽管 printf 和朋友们:与 print 不同,它们是真正的函数。)

那为什么 print(foo) 可以工作呢?

echo(foo) 工作的原因相同。这些括号与函数调用括号有很大不同,因为它们属于表达式。这就是为什么人们可能会编写 echo ( 5 + 8 ) 并期望显示 13 的结果(请参阅 参考)。这些括号涉及计算表达式而不是调用函数。注意:PHP 中括号还有其他用途,例如 if if 条件表达式、赋值列表、函数声明等。

为什么 print(1,2,3)echo( 1,2,3) 导致语法错误?

语法为 print exprecho exprecho expr, expr, ..., expr。当 PHP 遇到 (1,2,3) 时,它会尝试将其解析为单个表达式,但会失败,因为与 C 不同,PHP 实际上没有二元逗号运算符;逗号更多地用作分隔符。 (尽管如此,您仍然可以在 PHP 的 for 循环中找到一个二进制逗号,它的语法是从 C 继承的。)

语义

语句 echo e1, e2, ..., eN; 可以理解为 的语法糖。代码>回显e1;回显e2; ...;回声eN;

由于所有表达式都是语句,并且 echo e 总是与 print e 具有相同的副作用,并且 print e 的返回值被忽略当用作语句时,我们可以将echo e理解为print e的语法糖。

这两个观察结果意味着 echo e1, e2, ..., eN; 可以被视为 print e1; 的语法糖。打印e2; ...打印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 xprint x

echo 不同,print 分配一个临时变量。然而,花在这项活动上的时间很少,因此这两种语言结构之间的差异可以忽略不计。

速度:echo a,b,cecho abc

第一个编译为三个单独的语句。第二个计算整个表达式abc,打印结果并立即处理它。由于串联涉及内存分配和复制,因此第一个选项会更有效。

那么该使用哪一个呢?

在 Web 应用程序中,输出主要集中在模板中。由于模板使用 ,它是 echo 的别名,因此在代码的其他部分也坚持使用 echo 似乎是合乎逻辑的。 echo 的另一个优点是能够打印多个表达式而无需连接它们,并且不涉及填充临时返回变量的开销。因此,使用echo

Why two constructs?

The truth about print and echo is that while they appear to users as two distinct constructs, they are both really shades of echo if you get down to basics, i.e. look at the internal source code. That source code involves the parser as well as opcode handlers. Consider a simple action such as displaying the number zero. Whether you use echo or print, the same handler " ZEND_ECHO_SPEC_CONST_HANDLER" will be invoked. The handler for print does one thing before it invokes the handler for echo, it makes sure that the return value for print is 1, as follows:

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

(see here for reference)

The return value is a convenience should one wish to use print in a conditional expression. Why 1 and not 100? Well in PHP the truthiness of 1 or 100 is the same, i.e. true, whereas 0 in a boolean context equates as a false value. In PHP all non-zero values (positive and negative) are truthy values and this derives from PHP's Perl legacy.

But, if this is the case, then one may wonder why echo take multiple arguments whereas print can only handle one. For this answer we need to turn to the parser, specifically the file zend_language_parser.y. You will note that echo has the flexibility built in so that it may print one or multiple expressions (see here). whereas print is constrained to printing only one expression (see there).

Syntax

In the C programming language and languages influenced by it such as PHP, there is a distinction between statements and expressions. Syntactically, echo expr, expr, ... expr is a statement while print expr is an expression since it evaluates to a value. Therefore, like other statements, echo expr stands on its own and is incapable of inclusion in an expression:

5 + echo 6;   // syntax error

In contrast, print expr, can alone form a statement:

print 5; // valid

Or, be part of an expression:

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

One might be tempted to think of print as if it were a unary operator, like ! or ~ however it is not an operator. What !, ~ and print have in common is that they are all built into PHP and each takes only one argument. You can use print to create the following weird but valid code:

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

At first glance the result may seem odd that the last print statement prints its operand of '7' first. But, if you dig deeper and look at the actual opcodes it makes sense:

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

The very first opcode that gets generated is that corresponding to the 'print 7'. The '~0' is a temporary variable whose value is 1. That variable becomes and operand for the next print opcode which in turn returns a temporary variable and the process repeats. The last temporary variable doesn't get used at all so, it gets freed.

Why does print return a value and echo doesn't?

Expressions evaluate to values. For example 2 + 3 evaluates to 5, and abs(-10) evaluates to 10. Since print expr is itself an expression, then it should hold a value and it does, a consistent value of 1 indicates a truthy result and by returning a non-zero value the expression becomes useful for inclusion in another expression. For example in this snippet, the return value of print is useful in determining a function sequence:

<?php

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

if ( foo() ) {

     bar();
}

You might find print of particular value when it comes to debugging on the fly, as the next example illustrates:

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

// output: f not in abcde

As a side-note, generally, statements are not expressions; they don't return a value. The exception, of course are expression statements which use print and even simple expressions used as a statement, such as1;, a syntax which PHP inherits from C. The expression statement may look odd but it is very helpful, making it possible to pass arguments to functions.

Is print a function?

No, it is a language construct. While all function calls are expressions, print (expr) is an expression, despite the visual which appears as if it were using function call syntax. In truth these parentheses are parentheses-expr syntax, useful for expression evaluation. That accounts for the fact that at times they are optional if the expression is a simple one, such as print "Hello, world!". With a more complex expression such as print (5 ** 2 + 6/2); // 28 the parentheses aid the evaluation of the expression. Unlike function names, print is syntactically a keyword, and semantically a "language construct".

The term "language construct" in PHP usually refers to "pseudo" functions like isset or empty. Although these "constructs" look exactly like functions, they are actually fexprs, that is, the arguments are passed to them without being evaluated, which requires special treatment from the compiler. print happens to be an fexpr that chooses to evaluate its argument in the same way as a function.

The difference can be seen by printing get_defined_functions(): there is no print function listed. (Though printf and friends are: unlike print, they are true functions.)

Why does print(foo) work then?

For the same reason thatecho(foo) works. These parentheses are quite different from function call parentheses because they pertain to expressions instead. That is why one may code echo ( 5 + 8 ) and can expect a result of 13 to display (see reference). These parenthesis are involved in evaluating an expression rather than invoking a function. Note: there are other uses for parentheses in PHP, such as if if-conditional expressions, assignment lists, function declarations, etc.

Why do print(1,2,3) and echo(1,2,3) result in syntax errors?

The syntax is print expr, echo expr or echo expr, expr, ..., expr. When PHP encounters (1,2,3), it tries to parse it as a single expression and fails, because unlike C, PHP does not really have a binary comma operator; the comma serves more as a separator. ( You may find a binary comma nonetheless in PHP's for-loops, syntax it inherited from C.)

Semantics

The statement echo e1, e2, ..., eN; can be understood as syntactic sugar for echo e1; echo e2; ...; echo eN;.

Since all expressions are statements, and echo e always has the same side-effects as print e, and the return value of print e is ignored when used as a statement, we can understand echo e as syntactic sugar for print e.

These two observations mean that echo e1, e2, ..., eN; can be seen as syntactic sugar for print e1; print e2; ... print eN;. (However, note the non-semantic runtime differences below.)

We therefore only have to define the semantics for print. print e, when evaluated:

  1. evaluates its single argument e and type-casts the resulting value to a string s. (Thus, print e is equivalent to print (string) e.)
  2. Streams the string s to the output buffer (which eventually will be streamed to the standard output).
  3. Evaluates to the integer 1.

Differences at the bytecode level

print involves a small overhead of populating the return variable (pseudocode)

print 125;

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

single echo compiles to one opcode:

echo 125;

ECHO 125

multi-value echo compiles to multiple opcodes

echo 123, 456;

ECHO 123
ECHO 456

Note that multi-value echo doesn't concatenate its arguments, but outputs them one-by-one.

Reference: zend_do_print, zend_do_echo.

Runtime differences

ZEND_PRINT is implemented as follows (pseudocode)

PRINT  var, result:

    result = 1
    ECHO var

So it basically puts 1 in the result variable and delegates the real job to the ZEND_ECHO handler. ZEND_ECHO does the following

ECHO var:

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

where zend_print_variable() performs the actual "printing" (in fact, it merely redirects to a dedicated SAPI function).

Speed: echo x vs print x

Unlike echo, print allocates a temporary variable. However, the amount of time spent on this activity is minuscule, so the difference between these two language constructs is negligible.

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

The first one compiles down to three separate statements. The second evaluates the entire expression a.b.c., prints the result and disposes it immediately. Since concatenation involves memory allocations and copying, the first option will be more efficient.

So which one to use?

In web applications, output is mostly concentrated in templates. Since templates use <?=, which is the alias of echo, it seems logical to stick to echo in other parts of code as well. echo has an additional advantage of being able to print multiple expression without concatenating them and doesn't involve an overhead of populating a temporary return variable. So, use echo.

空名 2024-12-07 10:28:23

print 可以作为语句存在,而不需要 ;,这就是我们可以将其包含在 $b; 中的原因。打印“真”:打印“假”;

print may live as statement without the need of ;, and this is the reason that we may include it in a $b; print "TRUE": print "FALSE";

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文