みむらです。
「私と小鳥と鈴と」って中学か小学校かでやりませんでしたかね。
どうでもいいですね。ごめんなさい。
C でコードを書いていると、AND 演算や OR 演算をよく使うんですが、
よく “&” と “&&” だったり、 “|” と “||” を間違えていたりします。
や、眠たいときや全力で \バリバリバリバリ/ みたいなことしているときによくやるんですが、
自戒を込めてメモ。 たまにテストで填まった時によく確認するとこれ、ってこともあるので。
サンプル
#include <stdio.h>
int main(void){
int a = 0xFF;
int b = 0x64;
printf("BITWISE = 0x%x, LOGICAL = 0x%x",a&b,a&&b);
return 0;
}
実行するとわかりますが、結果として、
BITWISE = 0x64, LOGICAL = 0x1
こうなるかと思います。
つまり、
演算子 |
意味 |
& |
ビットごとの論理AND |
&& |
論理AND |
となるわけで、意味が異なります。
時に、C ですと、結果が 0 以外であれば TRUE として処理するように考えていますと、
演算子を書き間違えていたときに問題が起きるので、
該当箇所は func() != 0 というような感じで書いておくといいのかも、とふと。
OR 演算も同じような感じで。
#include <stdio.h>
int main(void){
int a = 0x100;
int b = 0x64;
printf("BITWISE = 0x%x, LOGICAL = 0x%x",a|b,a||b);
return 0;
}
もちろん結果も、
BITWISE = 0x164, LOGICAL = 0x1
こんな感じで変わってきます。
最後に高速化について。
C や C++ ではコンパイラによると思うので、私はよくわかりませんが、
C# においては、演算子の使い分けで高速化ができるようです。
& 演算子 (C# リファレンス)
http://msdn.microsoft.com/ja-jp/library/vstudio/sbf85k1c.aspx
&& 演算子 (C# リファレンス)
http://msdn.microsoft.com/ja-jp/library/vstudio/2a723cdk.aspx
こちらのウェブサイトを見比べるとわかるのですが、
& 演算子の場合は双方を評価して結果を出しますが、
&& 演算子の場合は単なる論理 AND のため、最初の演算で結果が確定する場合は2個目以降は演算しません。
要は、
funcA() & funcb()
とあった場合は、結果にかかわらず両方を演算し、
funcA() && funcb()
とあった場合、 funcA() が False を返す場合、 funcb() は実行されません。
これを応用すれば演算が最小限で済み、演算が高速になることが容易に考えられます。
(ただ、評価順を最適化する必要があるかとは思います。)
またやろうと思えば、
if(hoge.IsEnable() && hoge.type == Hoge.HOGEHOGE) { }
のような、有効なら細かく調査していく みたいなことも書けるのだとは思いますが、
私のような人には危険な気がしますが。
そんなこんなで特に私の場合、ビットごとの論理演算をしているかどうか。
これを間違えないようにコードを書きたいですね。
ってことで、よく間違いをやらかすのでメモ。
追記(2012/11/04 7:07):
記事についてコメントをいただきました。
最後の部分について、
世間では「ショートサーキット評価」と言うそうで、言語仕様で明確に定義されているとのこと。
http://ja.wikipedia.org/wiki/%E7%9F%AD%E7%B5%A1%E8%A9%95%E4%BE%A1
また、返値もブーリアンではなく最後に評価した値となる言語もあるようで、いろいろとおもしろそうです。