我想知道为什么以下输出7 7 6 7
而不是5 6 6 7
my $a = 5;
printf("%d %d %d %d",$a,++$a , $a++ , $a);
我很确定它与参数编译的顺序有关
谢谢,
答案 0 :(得分:14)
在开始之前,请允许我指出,通常应该避免在表达式中设置和读取变量的情况。
首先,让我们看一下操作数评估顺序。这不是为许多运算符定义的,而是为列表运算符定义的。记录下按从左到右的顺序评估其操作数 [1] 。这意味着printf
的参数按以下顺序进行评估:
"%d %d %d %d"
$a
++$a
$a++
$a
关键在于知道$a
没有在堆栈上放置$a
值的副本。它放置标量本身(用{C}表示SV*
。在Perl术语中,我们说堆栈元素别名到$a
[2] 。在计算理论中,你会说参数是通过引用传递。
同样适用于++$a
,但$a++
必须在堆栈上放置$a
的副本。
这意味着我们可以将上述printf
调用视为等同于
use Data::Alias qw( alias );
{
local @_;
alias $_[0] = "%d %d %d %d";
alias $_[1] = $a; # Places $a on the stack.
alias $_[2] = ++$a; # Adds one to $a and places $a on the stack.
alias $_[3] = $a++; # Places a copy of $a on the stack and adds one to $a.
alias $_[4] = $a; # Places $a on the stack.
&CORE::printf;
}
当$a++
被调用时,$a
包含6。
在调用printf
时,$a
包含7。
解决方法是复制值。
$ perl -le'$a = 5; my @b = ($a, ++$a, $a++, $a); print "@b";'
7 7 6 7
$ perl -le'$a = 5; my @b = (0+$a, 0+(++$a), $a++, $a); print "@b";'
5 6 6 7