Re: [Tokyo-pm] Re: これはどう動くの?
Dan Kogai
dankogai @ dan.co.jp
2004年 8月 26日 (木) 10:41:02 CDT
弾です。
それにしても早川君って「モツ好き」だよなあ....
On Aug 26, 2004, at 23:01, Shinya Hayakawa wrote:
> On 2004 8月 26 木曜日 8:48 午後, Keiichi Okabe wrote:
>> sub {substr(shift,0,-1), \@_}
>>
>> になるわけですよね.なんで@_じゃないのかな,という
>> ところから混乱を起こしました.でもなんで \@_に
>> なるんでし
>> ょう.何を見ればわかるでしょうか?
>
> my 変数と同様に、参照カウントを増やすことで
> スコープを抜けた後も、中身が解放されない事を利用してます。
え?この場合は、REFCNTは関係ないはず。以下を実行してみて実際のref countを確認してみてください。
perl -MDevel::Peek -le '@a=qw/a b c/; sub a{ \@_ }; $b=a(@a);Dump $b'
$b のREFCNTは1のまま。@$bのREFCNTも1のまま。というか1で充分。
#ただし、$b->[]の各要素のSVのref countは1づつ上がる。
#うむむ、むしろこちらの方が不(思議|可解)だ!
むしろこれがうまく行く理由は、@_そのものが、引数へのreferenceのarrayだから。機能的には、
sub { my $s = shift; substr($s,0,-1) => [ @_ ] }
と同じだけど、こちらの場合には、@_ の中身はコピーされるのに対し、早川版では
split(/\n/)
の結果のtemp arrayがそのまま用いられ、それが捨てられずに残るのです。
> 実装上は問題ないはずですが
> これって違法でしたっけ。
Perlの世界ではなかなか違反切符を切られる事はないので、この場合も動く(よね?自分で確認してないので)のではあるけど、夜中の首都高でハコ乗り
するぐらいコワい。
特にコワいのは、
substr(shift,0,-1), @_;
では同一statementで@_の内容を変更していること。shiftと@_とどっちが先に評価されるかというのはCでは未定義なんだよね(K&R
pp.
52)。perlでも明示的に定義はしてなかったように思うが、今のところどのplatformでもshiftの方が先に評価されるみたい。だけどCは
そうは行かない。
#include <stdio.h>
int inc(int *a){ return ++*a; }
main(){ int b = 0; printf("%d%d\n", inc(&b), inc(&b)); }
の結果と
perl -le 'sub inc{++$$_[0]}; $b=1; print inc(\$b), inc(\$b)'
の結果を比べると。perlでは一貫して"01"ですが、Cだと同じGCCでもFreeBSD 4では(-Oとかなしで)"21"、MacOS X
v10.3では"12"と逆ぶっこいてくれちゃいます。
Dan the Dirty Old Man
Tokyo-pm メーリングリストの案内