参考:比较PHP的打印和回显 [英] Reference: Comparing PHP's print and echo

查看:77
本文介绍了参考:比较PHP的打印和回显的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

PHP的printecho有什么区别?

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

Stack Overflow有很多问题,询问有关PHP的printecho关键字的用法.

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

这篇文章的目的是提供规范的引用print和echo关键字的问答,并比较它们的区别和用例.

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.

推荐答案

为什么要构造两个?

关于 print echo 的真相是,尽管它们在用户看来是两个截然不同的结构,但是如果您了解基础知识的话,它们实际上都是回声的阴影.看一下内部源代码.该源代码涉及解析器以及操作码处理程序.考虑一个简单的动作,例如显示数字零.无论使用echo还是print,都将调用相同的处理程序"ZEND_ECHO_SPEC_CONST_HANDLER". print的处理程序在调用echo的处理程序之前会做一件事,它确保print的返回值为1,如下所示:

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);

(请参阅此处以供参考)

如果希望在条件表达式中使用print,则返回值是一种便利.为什么是1,而不是100?在PHP中,真实性为1或100是相同的,即true,而布尔上下文中的0等同于false值.在PHP中,所有非零值(正值和负值)都是真实值,这是从PHP的Perl传统中得出的.

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.

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

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).

在C编程语言和受其影响的语言(如PHP)中,语句和表达式之间存在区别.从语法上讲,echo expr, expr, ... expr是语句,而print expr是表达式,因为它求值.因此,与其他语句一样,echo expr独立存在并且不能包含在表达式中:

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

相反,print expr可以单独构成一条语句:

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 

可能会想起print好像它是一元运算符,例如!~,但它不是运算符. !, ~ and print的共同点是它们全部内置在PHP中,并且每个仅接受一个参数.您可以使用print创建以下奇怪但有效的代码:

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

乍看之下,最后一个打印语句将其操作数打印为'7' first 的结果可能看起来很奇怪.但是,如果您更深入地研究实际的操作码,这是有道理的:

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

首先生成的操作码是与"print 7"相对应的操作码. 〜0"是一个临时变量,其值为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.

表达式计算得出的值.例如,2 + 3的计算结果为5,而abs(-10)的计算结果为10.由于print expr本身是一个表达式,因此它应该包含一个值并且确实如此,1的一致值表示真实结果,并且通过返回非零值,该表达式可用于包含在另一个表达式中.例如,在此代码段中,print的返回值对于确定函数序列很有用:

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

通常,语句不是表达式;他们没有返回值.当然,例外情况是使用print的表达式语句,甚至使用简单的表达式作为语句,例如1;(PHP从C继承的语法).表达式语句可能看起来很奇怪,但它非常有帮助,使得有可能使用将参数传递给函数.

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.

不,这是一种语言构造.尽管所有函数调用都是表达式,但print (expr)是表达式,尽管视觉效果看起来好像是在使用函数调用语法.实际上,这些括号是括号-expr语法,可用于表达式求值.这说明了以下事实:如果表达式是简单表达式(例如print "Hello, world!"),它们有时是可选的.对于更复杂的表达式,例如print (5 ** 2 + 6/2); // 28,括号可帮助评估表达式.与函数名称不同, print在语法上是关键字,在语义上是语言构造" .

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".

PHP中的语言构造"一词通常指的是伪"函数,例如issetempty.尽管这些构造"看起来与函数完全一样,但它们实际上是 fexprs ,也就是说,参数是传递给它们而不进行评估,这需要编译器进行特殊处理. print恰好是一个fexpr,它选择以与函数相同的方式求值.

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.

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

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.)

出于与echo(foo)相同的原因.这些括号与函数调用括号完全不同,因为它们与表达式有关.这就是为什么可以编码echo ( 5 + 8 )并期望显示13的原因的原因(请参见

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.

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

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.)

语句echo e1, e2, ..., eN;可以理解为echo e1; echo e2; ...; echo eN;的语法糖.

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

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

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.

这两个发现意味着echo e1, e2, ..., eN;可以看作print e1; print e2; ... print eN;的语法糖. (不过,请注意下面的非语义运行时差异.)

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.)

因此,我们只需要定义print的语义. print e,评估后:

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

  1. 评估其单个参数e type-casts 将结果值转换为字符串s. (因此,print e等同于print (string) e.)
  2. 将字符串s流式传输到输出缓冲区(其中最终将被流式传输到标准输出.
  3. 计算为整数1.
  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.

字节码级别的差异

print涉及填充返回变量(伪代码)的少量开销

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

单个echo编译为一个操作码:

single echo compiles to one opcode:

echo 125;

ECHO 125

多值echo编译为多个操作码

echo 123, 456;

ECHO 123
ECHO 456

请注意,多值echo不会串联其参数,而是将它们一个一地输出.

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

参考: zend_do_print zend_do_echo .

ZEND_PRINT 实现为跟随(伪代码)

ZEND_PRINT is implemented as follows (pseudocode)

PRINT  var, result:

    result = 1
    ECHO var

因此,它基本上将1放入结果变量,并将实际作业委托给ZEND_ECHO处理程序. ZEND_ECHO 执行以下操作

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)

其中zend_print_variable()执行实际的打印"(实际上,它仅重定向到专用的SAPI函数).

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

echo 不同, print 分配一个临时变量.但是,花在这项活动上的时间微不足道,因此这两种语言结构之间的差异可以忽略不计.

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.

第一个编译为三个独立的语句.第二个计算整个表达式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.

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

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.

这篇关于参考:比较PHP的打印和回显的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆