PHPとPerlでビット演算(排他的論理和)
ある方からPerlとPHPでビット演算子(排他的論理和)の挙動が違うのは何で?って質問されました。
何で?って言われても???なのですが、気になったので調べてみました。
例:print bin2hex( ( "1234567890A" ^ "eda01110c533bf51e42c2390276eae11" ) ); Perl => 54565204040706085a0572336266353165343263323339303237366561653131 PHP => 54565204040706085a0572
動きを見る限りでは、Perlでは計算しない文字はそのまま返却しています。
それにに対し、PHPでは計算しない文字はカットして返却しているようでした。
(cvsが見えないので情報だけで勘弁を)
/(php-src dir)/Zend/zend_operators.c ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) { zval op1_copy, op2_copy; if (op1->type == IS_STRING && op2->type == IS_STRING) { zval *longer, *shorter; char *result_str; int i, result_len; if (op1->value.str.len >= op2->value.str.len) { longer = op1; shorter = op2; } else { longer = op2; shorter = op1; } result->type = IS_STRING; result_len = shorter->value.str.len; result_str = estrndup(shorter->value.str.val, shorter->value.str.len); for (i = 0; i < shorter->value.str.len; i++) { result_str[i] ^= longer->value.str.val[i]; } if (result==op1) { STR_FREE(result->value.str.val); } result->value.str.val = result_str; result->value.str.len = result_len; return SUCCESS; } zendi_convert_to_long(op1, op1_copy, result); zendi_convert_to_long(op2, op2_copy, result); result->type = IS_LONG; result->value.lval = op1->value.lval ^ op2->value.lval; return SUCCESS; }
どっちが正しいのかヨク分かりませんが、Perlと同じ挙動をするようにしてみました。
カナリ適当なタコさんパッチですが、勢いでっ。
--- php-4.4.0,orig/Zend/zend_operators.c 2005-09-07 10:53:34.000000000 +0900 +++ php-4.4.0/Zend/zend_operators.c 2005-09-07 10:53:34.000000000 +0900 @@ -959,10 +959,10 @@ } result->type = IS_STRING; - result_len = shorter->value.str.len; - result_str = estrndup(shorter->value.str.val, shorter->value.str.len); + result_len = longer->value.str.len; + result_str = estrndup(longer->value.str.val, longer->value.str.len); for (i = 0; i < shorter->value.str.len; i++) { - result_str[i] ^= longer->value.str.val[i]; + result_str[i] ^= shorter->value.str.val[i]; } if (result==op1) { STR_FREE(result->value.str.val);
細かい部分の挙動の違いは仕方が無いんですけどねぇ。方言的なモンなんです、きっと。
しかしアレですね。zend_*_parser.*とか、zend_*_scanner.*とか見ると。。。
なんというか(できの悪い)テンプレート・エンジンを見ている錯覚が。。。流石に言い過ぎか。