Perl中的负数数组索引如何工作?

3

最近我在perl项目中接触到了负数索引。当我们给一个数组在perl中使用负数索引时,它会从后往前遍历。
例如:

@numbers = (1,2,3,4,5,6);
print "$numbers[-1]\n";

它将输出6。如果我给定索引为-2,那么它会打印5,以此类推。
根据我的理解,数组的内存如下图所示:
enter image description here 我想知道,在perl中,索引-1如何变成了n。有人能解释一下这是如何工作的吗?
附言:如果在java中使用负索引,则会抛出java.lang.ArrayIndexOutOfBoundsException异常。

你可以把 $numbers[-1] 理解为 $numbers[ @numbers-1 ]。另外请查看 https://dev59.com/7XDYa4cB1Zd3GeqPDrts。 - mpapec
@mpapec,Perl解释器会负责将“-1”转换为“@numbers-1”吗? - G.S
你可以这么说,但减号只是指示Perl从数组末尾获取元素。 - mpapec
答案在你友好的Perl手册中:http://search.cpan.org/~nwclark/perl-5.8.9/pod/perldata.pod#Subscripts。 - reinierpost
1
@reinierpost:你为什么要分享一个五年前的 Perl 版本的文档链接呢?肯定 http://perldoc.perl.org/perldata.html#Subscripts 更好吧? - Dave Cross
1
@Dave Cross:因为我看到的大多数Perl问题,至少在这个级别上,都源于那些最终发现正在使用10年甚至15年前版本的Perl的人。 - reinierpost
5个回答

9

请问有人能解释一下这是如何工作的吗?

Perl API调用获取数组元素av_fetch时,执行的是C语言等效操作:

my $real_index = $index < 0 ? @array+$index : $index;

更精确地说,或者详细了解

$index += $#array+1 if $index < 0;

6

更多关于索引的信息

我们之前提到过,数组索引是非负整数。虽然在某个层面上这是严格正确的,但Perl方便地允许您使用负索引从数组末尾开始索引元素。-1表示最后一个元素,-2表示倒数第二个元素,以此类推。简单来说,-1就像是 $#array 的别名......但仅限于索引 @array 的上下文中!

因此以下两种写法等价:

$array[ -1 ]
$array[ $#array ]

But beware:

@array[ 0 .. $#array ]

不能写成:

@array[ 0 .. -1 ]

因为在这种情况下,-1是..范围运算符的参数,它并不知道实际上想要什么“最高索引号”。


它之所以起作用,是因为当在数组索引的上下文中使用时,它实际上只是一个别名。


3

Perl 数组不是 C 数组,它们更像 Java 的 java.util.ArrayList。这种数据结构包括一些元数据,例如数组的长度,而非仅有开始指针。

当 Perl 的数组访问代码看到负索引时,它会添加数组的长度:n+1 是长度为 n+1 的数组中的索引 n,即 -1 + (n+1)。虽然这是一个方便的语言特性,但某些语言(尤其是类似于 C 的“系统编程语言”)希望避免隐含的开销。


1
这是一个已记录的功能。(请参阅perldoc perldata中的下标部分。)

0

虽然在某种程度上这是严格正确的,但Perl方便地让您使用负索引从数组末尾索引元素。-1表示最后一个元素,-2表示倒数第二个元素,以此类推。简单来说,-1充当$#array的别名...但仅在索引@array的上下文中!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接