perl - 编译顺序和后前缀运算符

标签 perl printf postfix-operator prefix-operator

我想知道为什么以下输出 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 的值的副本在堆栈上。它放置标量本身(一个 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
    

  • 来自 perlop , “在列表上下文中,它只是列表参数分隔符,并将其两个参数插入列表。这些参数也从左到右计算。”
  • 来自 perlsyn , "传入的任何参数都显示在数组 @_ 中。因此,如果您调用带有两个参数的函数,它们将存储在 $_[0]$_[1] 中。数组 @_ 是一个本地数组,但是它的元素是实际标量参数的别名。”
  • 关于perl - 编译顺序和后前缀运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16570415/

    相关文章:

    java - Java 中++ 和 -- 运算符的优先级

    c# - 为什么 Postfix++/-- 在 C# 中被归类为主要运算符?

    regex - 如何使用正则表达式解析 Perl 中引用的 CSV?

    perl - 关于编译时错误的问题

    c++ - Cout 不打印号码

    c++ - 将 va_list 传递给只接受变量参数的 #define (...)

    perl - 具有perl和sqlite的网站

    perl - 在 XML :TWIG, 中如何在找到感兴趣的元素后停止解析

    c - 如何在 C 中传递 char 数组并访问它的值

    java - 这里发生了什么 : sum += i++;?