php循环输出abcd,参考:比较PHP的打印和回声

为什么两个结构?

关于打印和回声的真相是,虽然它们在用户看来是两个不同的结构,但如果你了解基础知识,那么它们都是真正的回声阴影,即查看内部源代码。该源代码涉及解析器以及操作码处理程序。考虑一个简单的操作,例如显示数字零。无论您使用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的真实性是相同的,即为真,而布尔上下文中的0等于伪值。在PHP中,所有非零值(正数和负数)都是真值,这源于PHP的Perl遗产。

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

句法

在C编程语言和受其影响的语言(如PHP)中,语句和表达式之间存在区别。语法上,echo expr, expr, ... expr是一个语句while 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表示真实的结果,并且通过返回非零值,表达式变得有用于包含在另一个表达式中。例如,在此片段中,print的返回值在确定函数序列时很有用:<?phpfunction  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-conditional表达式,赋值列表,函数声明等。

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

语法是print expr,echo expr或echo expr, expr, ..., expr。当遇到PHP时(1,2,3),它会尝试将其解析为单个表达式并失败,因为与C不同,PHP实际上没有二进制逗号运算符; 逗号更多地用作分隔符。(你可以在PHP的for循环中找到一个二进制逗号,它继承自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并将结果值类型转换为字符串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

单个echo编译为一个操作码:echo 125;ECHO 125

多值echo编译为多个操作码echo 123, 456;ECHO 123ECHO 456

请注意,多值echo不会连接其参数,而是逐个输出它们。

运行时差异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 xvsprint x

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

速度:echo a,b,cvsecho a.b.c

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

那么哪一个使用?

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值