ようこそゲストさん

CPA-LABテクニカル

2008/03/15(土) PHPの配列管理方法を正しく理解する-ハッシュテーブルとZval

配列は、となりの家に行くときも、毎回毎回、近所の交番で道を尋ねる


PHPの配列の管理方法については、意外に日本語情報が少ない。
これがわかっていないと、PHPに備わる膨大な配列関数をうまく使いこなせない場面もあるのではないか。
というわけで、できる限りわかりやく説明を試みる*1
きっと目から鱗。
だとうれしいなあ。

PHPを使っている人は、C言語をたやすく扱うような凄腕と、htmlもおぼつかない初心者とのレベル乖離が激しく、ちまたには、超初心者用か、超難解系かどちらかしかないように思われる。
なるべく初級者が中級者に上がるためのステップとなるようにしたい。

*1 : 偉そうな言葉使いだが、勉強したてである

PHPの配列管理方法

PHPの配列型(array)の管理方法は、たらい回し方式である。現実の役所でのたらい回しは、腹が立つものだが、PHPにおいては、実に論理的にたらい回しされる。
前回までに、通常の変数のPHP内部での取り扱いを説明した。では今回は、array、配列について説明する。
PHP変数管理の目次はこちら


以下の変数がどのように内部的に処理されるかみてみよう。
$papa = array(
    2 => 'two' ,
    'iti' => 1 ,
    0 => 'three' ,
    'child' => array( 'pillow'  =>  'slobber' ),
);

$mama = 'aisitetu' ;
$fee = 300 ;

この図のようになる。(クリックして大きくしてください。)
php_array_sysytem3.jpg
この図が一番大事な結論である。

復習

通常の変数(スカラー変数)は、シンボルテーブルを使って2段階だった

配列型(array)の格納方法

array型は、自分の配列管理用のシンボルテーブル*2を作成し、キー値とZvalアドレスを結びつける。


このように、PHPは常にシンボルテーブル(ハッシュテーブル)によって、間接的に、変数名(配列のキー名)と値が結びつけられる。
多次元配列となっても、シンボルテーブルをその度に新たに作り、入れ子構造にしていくのだ。
これにより、PHPの変数管理は、速さと柔軟性を両立させているのだ。


Zvalの隣に、配列の次の値があるからといって、PHPは直接的に隣には移動しない。必ず、シンボルテーブルに立ち返り、次に取得するべきZvalのアドレスを確認してから、値を取得(変更)する。
だから、
隣の家(zval)に行くのにも、近所の交番(シンボルテーブル)で道を尋ねる
と形容してみた。
道に迷わないように、石やパンくずを落としていった、ヘンゼルとグレーテル(童話)のよう、ともいえる。
ていうか、隣の席の人に、アメリカのサーバー経由でインターネットメールを送るようなものともいえるかも。
え、もういいって。。。。

$papa [ 'iti' ] をどうやって探すか

  1. まず、 変数名 papa を探しに アクティブなシンボルテーブルを参照する
  2. すると、Zval #0001 に値があることがわかった。
  3. Zval#0001をみると、配列型と書いてあり、その配列用のシンボルテーブルのアドレスは、#99001だということだ
  4. #99001のシンボルテーブルの中から iti を探す*3と、Zval#0087 に値があることがわかった。
  5. Zval#0087をみると、数字の 1 だった。
という感じである。


2次元配列、3次元配列については、これを拡張していくだけである。

$papa['child']['pillow'] の取り出し方は、図の矢印をおってみていただきたい。

配列の順番(イタレーション*4

図をみればわかるように、キーと順番は、別々に管理されている*5
だから、キーが数字だからと言って、foreach文などで何も考えずに回すと、思った配列の順番とならなかったりする。

上記の例では、foreachでは、 2→iti→0→child の順番となる。

この順番は、基本的には定義順となる。先に定義した要素のキーから順番につけられる。
だから、foreachなどで順番にこだわってループさせたい場合は、定義順に気をつける必要がある。
ただし、ソートや、array_spliceなどを行うと、この順番は変更される。

たまにcakePHPでは、わざわざ キーが数字である場合に、キーの値だけを取り出して、foreach文を使用せずに、for 文で回して $array[ $i ]; 方式で処理している場合があるが、おそらく、明示的に、キーの順番で処理したいためであろう。

PHP変数管理の目次はこちら

 参考書籍、サイト

Extending And Embedding PHP (ペーパーバック)
原理から学ぶネットワーク・セキュリティ 第4回 ハッシュ関数
Super Technique 講座-ハッシュテーブル
スレッドとは、ハッシュテーブルとは
配列や連想配列について

*2 : ハッシュテーブルにて実装されている

*3 : 実際はハッシュテーブルなので、ハッシュによって、C言語で理解できる整数値に変換してC言語の配列から取り出すことになる

*4 : イタレーションとは、本来は「反復」の意味である

*5 : 実際には順番の数字が代入されているのではなくて、nextポインタと、prevポインタが登録されている

1: kotonoha 2012年03月07日(水) 午前11時32分

解説と図に出てくる zValがサンプルコードの中に出てきません。何か例をご提示頂けないでしょうか。


名前:  非公開コメント   

  • TB-URL  http://www.cpa-lab.com/tech/031/tb/
  • PHPの配列上限数-PHP変数管理 CPA-LABテクニカル spok
    ■配列の個数制限PHP*1では、配列の管理にハッシュテーブル(シンボルテーブル)を使用している。そのサイズは、実質31bitであり*2、上限は16進数で80,000,000、10進数では、21億4千7百83万3千6百48個となる。地球の人口は66億人を超え...