はじめに
今回は演算子に焦点をあて、同様の動きをする演算子や関数と比較検証を行います。
‘==’と‘===’
‘==’と‘===’とを比較します。‘===’は値だけではなく型も含めて比較を行う演算子です。
まずはベンチマークを取ってみます。
‘===’のほうが‘==’よりも僅かに速い結果となりました。
それでは実装を見ていきましょう。まずは‘==’です。
‘==’の実体はZend/zend_operators.c内のis_equal_function()にあります。is_equal_function()の中をみると、compare_functionで左辺と右辺の比較を行っていることが分かります。
次にcompare_function()を見ていきます。同じくzend_operators.cに書かれてます。
文字列と数値との比較について見ていきます。
文字列の場合、zendi_smart_strcmp()で文字列比較が行われます。この関数では文字列が数字のみでできた文字列かを変換しチェックを行い、その結果によって比較処理が異なります。
数値の場合、型がlong同士であればそのまま比較します。
数値の型が違うときはlongなほうの値をdoubleに変換して比較が行われます。
一方、‘===’の実体はZend/zend_operators.c内のis_identical_function()にあります。文字列と数値の場合についての関数の動きを見ていきます。
1474から1477行目でまず型のチェックを行い、型が違えばfalseを返して終了、同じなら値のチェックに入ります。
1478行目から型によってそれぞれの値のチェックが行われます。
型がnullの場合はもう片方の値の型もnullかどうか比較します。
1482から1489行目ではbool, long, resource, double型についてのチェックが行われ、値はC言語の‘==’演算子で比較が行われます。
1490行目からはstringの比較をしていて、文字列長の比較とmemcmpによる文字列の比較が行われます。
ここまででis_identical_function()の解説は終わりです。
‘==’では型を考慮しないので、違う型での比較をすることも考えた凝った構造に対して、‘===’では同じ型かを最初にチェックして同じ型の値同士で比較を行うため、シンプルな構造で余計な型の変換もありません。そのため、‘===’のほうが速い結果になったと考えられます。
is_nullと‘===’
is_null()は与えた引数がnullであるかどうかをチェックする関数です。
is_**関数はほかにもたくさんあり、いろいろとタイプをチェックする関数が用意されています。
- is_bool
- booleanであるかを調べる
- is_resource
- リソースかどうかを調べる
- is_long
- 整数型かどうかを調べる
- is_float
- float型かどうかを調べる
- is_string
- 文字列かどうかを調べる
- is_array
- 配列かどうかを調べる
- is_object
- オブジェクトかどうかを調べる
- is_numeric
- 数字または数値形式の文字列かどうかを調べる
- is_callable
- 関数としてコール可能な構造であるかどうかを調べる
まずはベンチマークを取ってみます。
‘===’のほうがis_null()よりも速い結果になりました。
is_null()の実装を見ていきましょう。is_null()はext/standard/type.cにあり、php_is_type()で実際の処理が行われています。
php_is_type()の中での処理は、207行目でis_null()に渡された引数を取得して212行目で渡された引数とチェックすべきタイプ(ここではnullかどうか)をチェックし、その結果を返しています。
php_is_type()はis_bool, is_longでは引数のtypeにIS_BOOL、IS_LONGを渡して呼ばれ、汎用的に使われます。
is_null()の中身を見ると、ボトルネックになっているような箇所はなさそうなので、演算子のほうが関数よりも速いためにis_null()よりも‘===’のほうが速い結果になったと言えます。