👮

安易な気持ちで左bitシフトしてはいけない(C/C++)

2022/12/24に公開

背景

業務で遭遇した不具合で、未定義動作を踏んでいました。
検索ではそのものズバリの記事が見当たらなかったので、第2の自分に向けて記事にします。

何が起きたか?

以下のようなコードで、複数の環境(OSも異なる)で、dataの値が環境によってことなる値になっていました。また、最適化をOFFにすると問題は発生せず、意図した操作になりました。

  double data = 0.0;
  long long lhs = 10000;
  long long rhs = 1;
  data = (double)(lhs << rhs);

負の値の左bitシフトは未定義動作

Microsoft Learnの左bitシフトを説明しているページにはこう書かれています。

符号付き数値をシフトして符号ビットが影響を受ける場合、結果は未定義です。 次の例では、符号ビットの位置まで 1 ビット左にシフトしたときにどうなるかを示しています。
左シフトと右シフト演算子 (<< と >>)

また、C99の規格(以下はドラフトですが)を参照すると、次のように書かれています。

An expression having signed promoted type is left-shifted and either the value of the expression is negative or the result of shifting would be not be representable in the promoted type
J.2 Undefined behavior

DeepL先生に翻訳してもらいましょう。

符号付き昇格型を持つ式が左シフトされ、式の値が負であるか、シフトの結果が昇格型では表現できない。

負の値(というより、負に評価される式)の左bitシフトは未定義動作です。
未定義動作の説明については、さまざまな素晴らしい記事があるのでそちらに譲ります。

参考文献

Discussion