ビット演算と…
問題
次は、ビット演算について。テストコードを6つの言語で書いてみましたが、今回もやはり1つだけ出力結果が違うものがありました。それはどれでしょうか?
program Project1; {$APPTYPE CONSOLE} var a: Integer; begin a := 2 and 1 shl 1; Write(a); end.
#include <iostream> using namespace std; int main(int argc, char* argv[]) { int a = 2 & 1 << 1; cout << a; return 0; }
package project1; public class Project1 { public static void main(String[] args) { int a = 2 & 1 << 1; System.out.print(a); } }
namespace project1 { public class Project1 { public static void Main() { int a = 2 & 1 << 1; System.Console.Write(a); } } }
<?php
$a = 2 & 1 << 1;
echo $a;
?>
a = 2 & 1 << 1 print a
解説
正解は「Delphi」。
Delphiだけが「0」を出力し、それ以外の言語は「2」と出力します。実は今回のコード、ビット演算自体に問題がある訳ではありません。普通に考えると、「まず2と1のANDは0、次にその0を1ビット左にシフトして…やはり0」という結果が得られると思いがちですが、演算子には優先順位があります。
問題のコードのように評価する順序を明示的に示していない場合、優先順位が高いものから順に評価されます。Delphi以外の言語では、ビットシフトの演算子「<<」の方が優先順位が高く、先に評価されます。一方Delphiでは「and」と「shl」は順位が同じであるため左から順に、つまり「and」が先に評価されます。このようなうっかりミスを防ぐためにも、言語の種類に限らず「(…)丸括弧」を明示的に指定すべきでしょう。
a := 2 and (1 shl 1);
int a = 2 & (1 << 1);