hnwの日記

PHPでも巨大な16進数が書けるようになった

今回は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


と言っても、PerlPHPと違ってWarningを出しつつも正しい結果を返すわけですから、一緒にするなって怒られそうですけどね。


第一、今更対応したところでPHP5.2.0以前が全部駆逐されるまでは安心してソースコード中で使えないわけですから、対応したことで逆に混乱することさえありそうです。2の32乗より大きい定数を使うようなソースコードって一体何なの?って疑問もありますが。


恒例のPHPの中のCソースコード貼り付けも今回はやめておきます。前回見た箇所の付近を見れば、zend_hex_strtod()というのがPHP5.2.1から実装されています。