GoからC++への移植
最近、C++の練習がてらAtCoderなどの競技プログラムをC++でもやり始めました。基本Go言語でやっているので、Go言語でプログラミングしてACしたあとに、C++に移植というスタイルでやっています。
Go言語からC++にポーティングする時に、演算子の優先度でバグったので情報共有しておきます。
バグったコード
具体的には、以下の式です
bit = x >> i % 2
この結果がC++とGoで異なり、どこでミスが発生しているのかを見つけるのにえらく苦労しました(まさか、ここの挙動が違うとは思いもしませんでした)。
実際に確認してみる
Go言語
package main
import "fmt"
func main() {
x := 0x55
for i := 0; i < 8; i++ {
fmt.Println(i, x>>i%2, (x>>i)%2, x>>(i%2))
}
}
上記のプログラムの実行結果は、以下になります
0 1 1 85
1 0 0 42
2 1 1 85
3 0 0 42
4 1 1 85
5 0 0 42
6 1 1 85
7 0 0 42
C++
#include <iostream>
using namespace std;
int main()
{
int x = 0x55;
for (int i = 0; i < 8; i++)
{
cout << i << " " << (x >> i % 2) << " " << ((x >> i) % 2) << " " << (x >> (i % 2)) << endl;
}
}
上記のプログラムの実行結果は以下になります。
0 85 1 85
1 42 0 42
2 85 1 85
3 42 0 42
4 85 1 85
5 42 0 42
6 85 1 85
7 42 0 42
演算の解釈が違っていた
この結果から、Go言語では(x >> i)%2
、C++ではx >> (i%2)
と解釈されていることがわかります。
演算子の優先度を見ると、>>
と%
はGo言語では同じレベル、C++言語では、%
の方が>>
より優先です。同じレベルなのでGoでは左から右へ結合されたようです。
こんな違いがあると思っていなかったので、見つけるのにかなり苦労しました。
結論
「演算には()
を明示的につけたほうが良い」ということは知っていたのですが、サボってました。やはり、明示的にカッコをつけた方が良いようです。
今回、基本的な演算子でも、言語で優先度が違うということがわかりましたので、これからは注意してカッコをつけようと思いました。
Python, Javaを調べましたが、この2つはC++と同じみたいです。Goが珍しいのかも・・・・