今回はPHPの16進リテラルの話題です。前回の8進リテラルの話題の反応が薄かったので、今回もウケは良く無さそうです。
さて、早速ですがPHP5.2.0以前を用意して、16進リテラルで少し大きい数を扱ってみます。
$ php --version PHP 5.2.0 (cli) (built: Jul 4 2007 20:12:33) Copyright (c) 1997-2006 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2006 Zend Technologies $ php -r 'var_dump(0x7fffffff);' int(2147483647) $ php -r 'var_dump(0xffffffff);' float(4294967295) $ php -r 'var_dump(0x100000000);' PHP Notice: Hex number is too big: 0x100000000 in Command line code on line 1 int(2147483647)
このように、PHP5.2.0以前では2の32乗を超える大きさの16進リテラルには対応していません。
これがPHP5.2.1以降だと期待通りの結果を得られます。
$ php --version PHP 5.2.1 (cli) (built: Jul 4 2007 20:25:55) Copyright (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies $ php -r 'var_dump(0x7fffffff);' int(2147483647) $ php -r 'var_dump(0xffffffff);' float(4294967295) $ php -r 'var_dump(0x100000000);' float(4294967296)
下記の通り、これはPHP5.2.1で新たに対応したものです。
●Added support for hex numbers of any size. (Matt)
PHP 5 ChangeLog
前回の話と合わせて僕が面白いと思うのは、大きな8進リテラルや16進リテラルに今更対応することについてです。言語としてlongを超えるサイズの8進リテラルや16進リテラルが書けないとしても、Cに合わせたという説明ができる箇所ですので、これを仕様としてしまえば問題がないと僕は思っていました。実際、Perlでは2の32乗より大きい16進リテラルや8進リテラルに対してWarningを出します。
$ perl -e 'print 0xffffffff; print "\n";' 4294967295 $ perl -e 'print 0x100000000; print "\n";' Integer overflow in hexadecimal number at -e line 1. 4294967296
と言っても、PerlはPHPと違ってWarningを出しつつも正しい結果を返すわけですから、一緒にするなって怒られそうですけどね。
第一、今更対応したところでPHP5.2.0以前が全部駆逐されるまでは安心してソースコード中で使えないわけですから、対応したことで逆に混乱することさえありそうです。2の32乗より大きい定数を使うようなソースコードって一体何なの?って疑問もありますが。
恒例のPHPの中のCソースコード貼り付けも今回はやめておきます。前回見た箇所の付近を見れば、zend_hex_strtod()というのがPHP5.2.1から実装されています。