我想知道为什么以下输出7 7 6 7
而不是5 6 6 7
my $a = 5;
printf("%d %d %d %d",$a,++$a , $a++ , $a);
我很确定这与参数编译的顺序有关
谢谢,
我想知道为什么以下输出7 7 6 7
而不是5 6 6 7
my $a = 5;
printf("%d %d %d %d",$a,++$a , $a++ , $a);
我很确定这与参数编译的顺序有关
谢谢,
在开始之前,让我指出,通常应该避免在表达式中设置和读取变量的情况。
首先,让我们看一下操作数的评估顺序。这不是为许多运算符定义的,但它是为列表运算符定义的。它被记录为以从左到右的顺序评估其操作数[1]。这意味着printf
的参数按以下顺序评估:
"%d %d %d %d"
$a
++$a
$a++
$a
关键在于知道$a
不会将值的副本$a
放在堆栈上。它放置标量本身(a SV*
,在 C 术语中)。在 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