$なし変数のカラクリと数値変換のお話 ― 2007年12月18日 03時44分58秒
しつこくPHPのクサレ独特の仕様についてのエントリ。だって予想外の動作ばっかりなんですもの。
できそこない変数が文字列として解釈されるワケ
昨日のエントリの「$を付け忘れた変数が文字列として解釈される」についてだが、k_37to氏のはてブコメントに解説があった。
この場合「ijk」は定数としてパースされ、定数が存在しない場合は定数名の文字列として変換される。PHPのはまりやすい罠。定数か! 普段は慣習的に定数を大文字で記述してるので見落としていたが、なるほど定数名は定義上先頭に「$」が付かないこと以外は変数と同じだ。k_37toのブックマーク / 2007年12月17日(強調:dara-j)
そんで、マニュアルの「定数」の項を確認すると確かに
未定義の定数を使用した場合、ちょうどstringとして コールしたかのように(CONSTANT vs "CONSTANT")、 PHPはその定数自体の名前を使用したと仮定します。と書いてある。これで納得。つか、未定義の定数の仕様を許容するなよ。PHP: 定数 - Manual(強調:dara-j)
大きな数値の怖いお話
これも暗黙の型変換に関連するのだが、今度は数値。PHPSPOTさんの記事で紹介されていた記事より。
ここで上げられていた例は、2つの17桁の数値「11111111111111111」と「11111111111111112」が等値と判断されるという、なんとも理解しがたい現象。
詳しくはリンク先を見ていただくとして、要約すると
17桁の整数 → INTの範囲外なので自動的にFLOATに → FLOATの桁精度が足りなく丸め誤差発生 → 同じ値ってことで。ということらしい。
いや、数値なので精度による丸め誤差が発生するのはわかるんだけど、これに例の必殺技「==で比較すると整数に見なしちゃうぞ」が絡むと、
C:\Documents and Settings\dara-j>php -r "echo '11111111111111111' == '11111111111111112' ? 'equal' : 'not equal';" equal C:\Documents and Settings\dara-j>なんて、常識的なアタマではとても思いつかない奇ッ怪な結果が提示されたりする。回避するには文字列にキャストしてstrcmp()を使用するなんて、なんとも
結論
PHPは余計なお世話至れり尽せりの自動変換を施してくれるので、なるべく型を意識し、値の比較時は「===」による厳密な比較を行うか、文字列経由でstrcmp()を使うなどの工夫が必要、ってとこか。って、変数に型がないのに型を強く意識したプログラミングっておかしくないか?
最近のコメント