Perl增量运算符

Abh*_*aha 10 perl

$a = 10; 
$b = (++$a) + (++$a) + (++$a);
print $b;
Run Code Online (Sandbox Code Playgroud)

我得到答案37.任何人都可以解释这个操作是如何进行的以及结果如何得到37.

根据我的逻辑,它应该是36:

(++$a) + (++$a) + (++$a)
   11  +    12  +    13  = 36
Run Code Online (Sandbox Code Playgroud)

但我得到答案37

Bor*_*din 9

Perl正在执行此操作

( ( $a = $a + 1 ) + ( $a = $a + 1 ) ) + ( $a = $a + 1 )
Run Code Online (Sandbox Code Playgroud)

你甚至++$a在括号中加上括号,说它们应该在添加之前首先发生,尽管它们具有更高的优先级

这是以赋值运算符=返回其第一个操作数的事实为中心的,这允许像这样的操作

(my $x = $y) =~ tr/A-Z/a-z/
Run Code Online (Sandbox Code Playgroud)

如果分配的结果是根本的价值从复制$y$x那么tr///将导致无法修改一个常数项或等价物,它会对什么是存储在任何一个变量没有影响

这是变量$a,执行如下

  • 执行第一个增量,$a
    $a现在返回11

  • 执行第二个增量,现在$a再次返回
    $a12

  • 执行第一个添加,添加两个增量返回的内容 - 两者$a
    $a都是12,因此$a + $a是24

  • 执行第三个增量,现在$a再次返回
    $a13

  • 执行第二次添加,添加第一次添加(24)返回的内容,第三次增量($a)
    $a为13,因此24 + $a是37

请注意,这不应该依赖.它没有记录在任何地方,只是说我们未定义,并且行为可能会随着Perl的任何发布而改变


yst*_*sth 6

作为mob和Borodin答案的补充,如果你考虑操作如何与堆栈交互并认识到preinc返回变量而不是它的值,你可以清楚地看到发生了什么.

op | a's value | stack
$a | 10        | $a
++ | 11        | $a
$a | 11        | $a $a
++ | 12        | $a $a
+  | 12        | 24
$a | 12        | 24 $a
++ | 13        | 24 $a
+  | 13        | 37
Run Code Online (Sandbox Code Playgroud)

  • 如图所示,关键是`$ a`本身放在堆栈上,而不是它的副本 (2认同)

zdi*_*dim 5

正如在注释中所指出的那样,在单个语句中多次更改变量会导致未定义的行为,如perlop中所述.

因此,未指定确切的行为,并且可能因版本和实现而异.

至于如何运作,这是一种看待它的方法.由于+是二元运算符,因此在每个操作中,当左侧操作数++在另一个操作上执行时,它的左侧操作数会参与其中.因此,在每个位置$a进行++编辑,并选择另一个增量作为LHS操作数.

这意味着LHS 在每次操作中$a额外增加(到它++)一次+.在+后的第一个操作必须积累这些,一个额外的每个额外的项.这里有三个术语,是另一个+3,一次.所以总共有7个增量.

另一个(第四个)术语会产生额外的+4等

perl -wE'$x=10; $y = ++$x + ++$x + ++$x + ++$x; say $y'  # 4*10 + 2+2+3+4
Run Code Online (Sandbox Code Playgroud)

这是有趣的改变来调整++$x$x++-效果取决于位置.

步数增加

  • $a增加(到11)

  • 在第一个添加中,当第二个$a增加(到11)时,第一个获得一个凸起以及一个操作数(到12)

  • 在第二次添加中,第二次$a作为操作数递增(到12)

  • 当第二个加法出现时,第三个加法$a更新,从而从两个加法中加上增量,加上它的增量(到13)

$a上面的列举是指它们出现在声明中的多个位置.