uninitialized value

以下のプログラムを動かします.実行結果も特におかしいところはありません.

#!/usr/bin/perl

my @arr=(1,2,3,4,5);
my @printValue=@arr[3..5];
print @printValue;
  

実行結果

bash-2.05$ ./sam.pl
4 5
  

同じプログラムを-wオプションをつけて実行します.

#!/usr/bin/perl -w

my @arr=(1,2,3,4,5);
my @printValue=@arr[3..5];
print "@printValue\n";
  

実行結果です.

bash-2.05$ ./sam.pl
Use of uninitialized value in join or string at ./sam.pl line 5.
4 5
  

5行目のprint "@printValue\n";で初期化していない値を使っていると警告が出ています.しかし,@printValueはその前の行で値を設定しています.初期化していないはずはありません.

この原因はこう言うことです.まず,3行目のmy @arr=(1,2,3,4,5);では,配列@arrに以下のように値が入ります.

my @arr=(1,2,3,4,5);
$arr[0]=1;
$arr[1]=2;
$arr[2]=3;
$arr[3]=4;
$arr[4]=5;

その次の4行目my @printValue=@arr[3..5];ではこうなります.

my @printValue=@arr[3..5];
$printValue[0]=$arr[3]; #この値は4
$printValue[1]=$arr[4]; #この値は5
$printValue[2]=$arr[5]; #この値はundef

そして,エラーが発生したの5行目です.

print "@printValue\n";
print $printValue[0]; #4を表示
print $printValue[1]; #5を表示
print $printValue[2]; #undefを表示しようとしてエラー

print @printValue;で発生した警告の原因は,その前の行my @printValue=@arr[3..5];にありました.添字が4までしかない配列@arrの5番目の添字を参照しているのが原因です.配列@printValue自身を初期化していないのではなく,配列@printValueの要素に初期化していないものがあるわけです.

3番目から最後の要素までを出力しようと,@arrをスカラコンテキストで使った場合にも注意が必要です.@arrをスカラコンテキストで使うと@arrの「要素数」を返します.@arrの要素数ですから,5です.

#!/usr/bin/perl -w
use strict;

my @arr=(1,2,3,4,5);
my @printValue=@arr[3..@arr]; #スカラコンテキストで@arrを使う.要素数5
print "@printValue\n";
  

実行結果はこうなります.

bash-2.05$ ./sam.pl
Use of uninitialized value in join or string at ./sam.pl line 6.
4 5
bash-2.05$
  

添字の最大は$#arrです.3番目から最後の要素までなら,こう書きます.

#!/usr/bin/perl -w
use strict;

my @arr=(1,2,3,4,5);
my @printValue=@arr[3..$#arr]; #要素数@arrではなく添字の最大$#arr.添字の最大4
print "@printValue\n";
  
bash-2.05$ ./sam.pl
4 5
  

動作環境は,WindowsNT Workstation 4.0+SP6,cygwin 1.3.3,perl 5.6.1,bash 2.05です.