ようこそゲストさん

CPA-LABテクニカル

メッセージ欄

2008年1月の日記

一覧で表示する

2008/01/28(月) 変数の代入は、値のコピーにあらず-PHP変数管理 (3)

前回の変数管理の基礎(PHPの参照とは何か) でシンボルテーブルについて説明した。これがわかっていないとPHPの変数管理はわからない。


今回は、もっとも基本的な変数の値の代入、について説明する。
code1
$a=$b

なぜ、こんな単純なことをいちいち説明しなければならないのか。

続きを読む

  • issetを正しく理解する。null値とunsetの違い-PHP変数管理 CPA-LABテクニカル spok
    nullほど人を惑わすものはないだろう。設定されてない値ってなんだ?unsetされた変数とは違うの?様々な疑問があろう。ここで、明確な理解をしておきたい。(PHPの場合)シンボルテーブルのおさらい以前に変数管理の基本として書いたけれども、PHPは、シンボル...

2008/01/27(日) 変数管理の基礎(PHPの参照とは何か)-PHP変数管理 (2)

内部構造がわからず、もやもやとした気分でコーディングするのは、あまり気分が良くない。
PHPの変数管理の詳細を知ると、複雑な参照代入や配列などの使い方の幅が増えてくる。はず、ということで、いろいろ調べてみた。変数や関数の受け渡しについては知っているつもりで、間違った知識で書いていることも多いことがわかり、自分でもあぜんとした。ので、いくつかわかった(つもり)のことを書いてみる。

続きを読む

変数管理はワンクッションあり→シンボルテーブル

PHPで、$a='one';と書いた場合、内部的に 変数名a → 値one という単純な表が作られるわけではない。「変数名aは、値の格納庫コンテナ(zval構造体)No.#0001と対応している」というシンボルテーブルが作られ、格納庫(zval)No.#0001にoneという値が書き込まれる。
code1
$a='one';

figure1  $a='one'; で作成されるPHP内部の変数管理表
シンボルテーブル
変数名格納庫(zval)No.
a#0001

格納庫(zval)
No.valuetype
#0001onestring(文字列型)
格納庫zvalについては別ページで改めて説明する。

参照代入とは  -シンボルテーブルの多重割り当て


シンボルテーブルには、同じ格納庫(zval)No.に、複数の変数名が割り当てられることがある。それが参照代入と呼ばれる。
例えば、以下のコードは、同じ格納庫(zval)No.にa,bの変数名が割り当てられる。
code2
$a= <span style="color:red;font-weight:bold;">&</span> $b; 
figure2  参照代入された後
シンボルテーブル
変数名格納庫(zval)No.
a#0001
b#0001

格納庫(zval)
No.type
#0001onestring
このような構造だからこそ、
code3
$a='one';
$b= & $a;
$b= 'two';
としたとき、同じ格納庫(zval)No.に書き込まれるわけだから、$a,$bともに two となる。
ここで実体と呼ばれる、スカラー値が入った格納庫zvalは、決してコピーされていないことに注意する。実体はただ1つ。上の例では、その1つの実体をを呼ぶのに$aとも$bとも使われるわけだ。

C言語のポインタとの違い

ここが、C言語のポインタと違うと言われる理由である。C言語のポインタと同じものでであれば、以下のようになっているはずである。

figure3
シンボルテーブル
変数名格納庫(zval)No.
a#0001
b#0002

格納庫(zval)
No.type
#0001onestring
#0002#0001(long?)
※もし、PHPの参照代入がC言語のポインタと同じだったらの例示

この違いを理解しておかないと、後々、いろんなところで、「はまる」ことになる。

$aと$bは等価である。($a =& $b)  -ただし、$a,$bがオブジェクトの時は除く

以下のコードは同じ結果となる。$aと$bは等価である。
code4
$a='one';
$b= & $a;
$a= 'two';

code5
$a='one';
$b= & $a;
$b= 'two';

結果は以下のとおり。

figure4
シンボルテーブル
変数名格納庫(zval)No.
a#0001
b#0001

格納庫(zval)
No.type
#0001twostring

誤解されがちなのは、=&演算子が、参照「代入」と翻訳されていることから、$b=& $a;としたときに、まるで、$bに何かの値が書き込まれるような感覚になることである。それはCのポインタであり、PHPの参照とは違うことをよく理解する必要がある。あくまでも、PHPの参照代入は、結びつけるべき左辺の変数名をシンボルテーブルに追加することである。シンボルテーブルを利用して、変数名と格納庫(zval)Noを新たに連動させる、ということである。
誤解を恐れずにいえば、$b=& $a;の場合、$bの実体(zval格納庫)はないのだ。もう少し正確にいえば、$aの実体を間借りするようなものだ。この間借りすることをもって、エイリアスという言い方をする人がいるようだ。もっと正確にいえば、$aと$bは等価なので、$aの実体を$bの実体としても扱う、ということになる。


ただし、上記は、オブジェクトの時だけは異なった結論になる。それは、のちほど説明したい。

unset と =null の違い

では、ここでunset($a)としたら、どうなるか。
$a=null;とどう違うか、検証する。

まず、$a=nullであれば、格納庫(zval)No.#0001にnull値が書き込まれるわけだから、$a,$bともにnullとなる。$a,$bは連動しているのだ。

ではunsetはどうだろうか。
code6
unset($a);
unsetは、「変数を破棄する」でない。「シンボルテーブルからその変数名を削除する」という動作をする。つまり、
figure5
シンボルテーブル
変数名格納庫(zval)No.
a(削除)#0001(削除)
b#0001

格納庫(zval)
No.type
#0001twostring


となるので、$aはなくなってしまうが、$bの値はtwoのままである。

つまり
code7
$a='one';
$b= & $a;
$a= 'two';
unset ($a);
とすると、$bの値は、 two となる。

Ohhh!まるで、$bが$aをヤドカリのように乗っ取ってしまったようだ。

まとめ

このようにPHPでは、変数の名前とその値は切り離されており、シンボルテーブルがそれを結びつける働きをしている。シンボルテーブルでは、複数の変数名に対して、同じ実際の値(実体:zval構造体に収納)を、対応(reference or asign)させるさせることができるため、柔軟な変数運用をすることができる。

figure6
変数名($a)→シンボルテーブル→実際の値(実体:zval構造体に収納)
変数名($b)
変数名(・・・)


次回は、$a=$b;について説明したい。単純であるが、奥が深いcodeである。


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

1: FCC 『おー。それしらんかっとんてんちんとんしゃん』 (2011/11/28 10:27)

  • 変数の代入は、値のコピーにあらず CPA-LABテクニカル spok
    前回の変数管理の基礎(PHPの参照とは何か) でシンボルテーブルについて説明した。これがわかっていないとPHPの変数管理はわからない。今回は、もっとも基本的な変数の値の代入、について説明する。code1$a=$bなぜ、こんな単純なことをいちいち説明しなけれ...

2008/01/26(土) はじめに-PHP変数管理解説(1)-参照と値渡しの明確な理解のために

PHPの参照はおかしいか?

「PHP5からオブジェクトは参照渡しに変更になった」というのはウソである。PHP4からPHP5への以降は、PHPで混乱している「参照」という用語を統一するせっかくのチャンスであったのに、PHPコミュニティ(又はZEND社)は重大な過ちを犯した。同じreference(s)という言葉を使っても、「シンボルテーブルを使った参照」と、(C言語のような)「ポインタを利用した参照」は、その原理も使い方も全く異なるのに、同じ「参照」という言葉を使ったがために、大きな混乱を呼んでいるように思う。

このカテゴリの記事について

この連載は、PHPの変数管理、特に参照代入と値渡し(コピー)代入の不十分な理解に基づく混乱を少しでも収束させるために書いた。実際は、自分自身がわからなくて、改めて調べ直したものである。言葉遣いは偉そうだが、これは簡潔に書くためであって、決して偉ぶっているわけでも、その道のプロであるわけでもない。

続きを読む

目次と今後の予定

  1. はじめに(この記事)
  2. PHPの変数管理(メモリ管理)の基礎
  3. 変数の代入は、値のコピーにあらず
  4. issetを正しく理解する。null値とunsetの違い-PHP変数管理
  5. PHPの配列管理方法を正しく理解する-ハッシュテーブルとZval
  6. PHPの配列上限数-PHP変数管理
(今後の予定)
一般の値の代入、配列の管理、オブジェクトの管理、グローバル変数の管理、スタティック変数の管理

続きを読む

1: hashi 『PHPの何が嫌いって、変数管理がわかりずらいとこでした。この記事で大分すっきりしました。』 (2008/05/21 12:37)

2: ookami 『このウェブサイトも役に立つと思うよ 使ってみよう http://bbs.flatworld.jp/forum/65』 (2010/12/14 24:52)

3: taka_taka 『参考になります。助かりました。』 (2012/07/30 7:26)