[インデックス 16282] ファイルの概要
このコミットは、Go言語の公式仕様書 doc/go_spec.html
における誤ったコード例を修正するものです。具体的には、定数に対するビットシフト演算の挙動に関する記述が、Go言語の仕様に合致するように更新されました。
コミット
commit 2d846f65215cd35eb03b79871f79f03383df67cb
Author: Robert Griesemer <gri@golang.org>
Date: Wed May 8 10:42:08 2013 -0700
spec: fix incorrect example
Fixes #5430.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9305043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2d846f65215cd35eb03b79871f79f03383df67cb
元コミット内容
このコミットは、Go言語の仕様書 doc/go_spec.html
の以下の部分を修正しています。
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{\n \t\"Title\": \"The Go Programming Language Specification\",\n-\t\"Subtitle\": \"Version of April 10, 2013\",\n+\t\"Subtitle\": \"Version of May 8, 2013\",\n \t\"Path\": \"/ref/spec\"\n }-->\n \n@@ -3835,7 +3835,7 @@ const Θ float64 = 3/2 // Θ == 1.0 (type float64, 3/2 is integer divisio\n const Π float64 = 3/2. // Π == 1.5 (type float64, 3/2. is float division)\n const d = 1 << 3.0 // d == 8 (untyped integer constant)\n const e = 1.0 << 3 // e == 8 (untyped integer constant)\n-const f = int32(1) << 33 // f == 0 (type int32)\n+const f = int32(1) << 33 // illegal (constant 8589934592 overflows int32)\n const g = float64(2) >> 1 // illegal (float64(2) is a typed floating-point constant)\n const h = \"foo\" > \"bar\" // h == true (untyped boolean constant)\n const j = true // j == true (untyped boolean constant)\n```
主な変更点は、`const f = int32(1) << 33` という定数宣言のコメントです。
* 変更前: `// f == 0 (type int32)`
* 変更後: `// illegal (constant 8589934592 overflows int32)`
また、仕様書のバージョン日付も「April 10, 2013」から「May 8, 2013」に更新されています。
## 変更の背景
このコミットは、Go言語のIssue #5430 に対応するものです。Issue #5430は、Go言語の仕様書に記載されている定数に対するビットシフト演算の例が、実際のGoコンパイラの挙動と一致しない、あるいはGo言語の定数オーバーフローに関するルールと矛盾していることを指摘していました。
具体的には、`int32(1) << 33` という式は、`int32` 型の `1` を左に `33` ビットシフトすることを意味します。`int32` は32ビット符号付き整数型であり、その最大値は `2^31 - 1` です。`1` を `33` ビット左シフトすると、結果は `2^33` となり、これは `int32` の表現範囲をはるかに超えます。
Go言語の定数に関するルールでは、定数式がその型に収まらない場合、コンパイル時にエラーとなるべきです。しかし、元の仕様書の例では、このオーバーフローが `0` になると誤って記述されていました。このコミットは、この誤りを修正し、Go言語の定数オーバーフローの厳密なルールを反映させることを目的としています。
## 前提知識の解説
### Go言語の定数
Go言語における定数(`const`キーワードで宣言される値)は、コンパイル時に評価される不変の値です。定数には「型付き定数」と「型なし定数」の2種類があります。
* **型なし定数 (Untyped Constants)**: 型が明示的に指定されていない定数です。Goコンパイラは、その値が使用される文脈に基づいて適切な型を推論します。例えば、`const x = 10` の `10` は型なし整数定数です。型なし定数は、より大きな精度で表現できるため、計算の途中でオーバーフローしにくいという特性があります。
* **型付き定数 (Typed Constants)**: 型が明示的に指定されている定数です。例えば、`const x int32 = 10` の `10` は型付き `int32` 定数です。型付き定数は、その宣言された型の範囲内に収まる必要があります。
### ビットシフト演算子 (`<<`, `>>`)
Go言語におけるビットシフト演算子は、数値のビットを左右に移動させます。
* `x << n`: `x` のビットを左に `n` ビットシフトします。これは `x * 2^n` と同等です。
* `x >> n`: `x` のビットを右に `n` ビットシフトします。これは `x / 2^n` と同等です(整数除算)。
シフト演算の左オペランドは整数型または型なし整数定数でなければなりません。右オペランドは符号なし整数型または型なし整数定数でなければなりません。
### 整数オーバーフロー
整数型には表現できる値の範囲に限りがあります。計算結果がその型の最大値を超えたり、最小値を下回ったりすることを「オーバーフロー」と呼びます。
Go言語では、実行時の整数オーバーフローはエラーとはなりません(ラップアラウンド挙動を示します)。しかし、**コンパイル時の定数式におけるオーバーフローは、その定数が型付きである場合、コンパイルエラーとなります。** 型なし定数の場合は、その値が最終的に型付き変数に代入されるか、型付き定数として使用される際に、その型の範囲に収まるかどうかがチェックされます。
### `int32` 型
`int32` はGo言語の組み込み型で、32ビット符号付き整数を表します。その値の範囲は `-2,147,483,648` から `2,147,483,647` までです。これは `-(2^31)` から `2^31 - 1` に相当します。
## 技術的詳細
このコミットの核心は、Go言語の定数評価における厳密な型チェックとオーバーフロー検出の挙動を正確に反映させることです。
元の仕様書では、`const f = int32(1) << 33` の結果が `0` になるとされていました。これは、C言語などの一部の言語で、シフト量が型のビット幅以上の場合に未定義動作になったり、あるいはシフト量が型のビット幅を法とする値として扱われたりする挙動(例えば32ビット型で33ビットシフトが1ビットシフトとして扱われる)を連想させるかもしれません。しかし、Go言語の定数式評価はより厳密です。
Go言語の仕様では、シフト演算の左オペランドが型付き定数である場合、シフト結果も同じ型になります。この場合、`int32(1)` は型付き `int32` 定数です。`1` を `33` ビット左シフトすると、数学的には `2^33` となります。
`2^33` は `8,589,934,592` です。
一方、`int32` 型が表現できる最大値は `2^31 - 1 = 2,147,483,647` です。
`8,589,934,592` は `2,147,483,647` を明らかに超えています。したがって、`int32(1) << 33` という定数式の結果は `int32` 型の範囲に収まらないため、Goコンパイラはこれを「オーバーフロー」と判断し、コンパイルエラーとします。
このコミットは、このGo言語の定数評価の厳密なルールを仕様書に明記することで、開発者の誤解を防ぎ、言語の挙動とドキュメントの一貫性を保つことを目的としています。
## コアとなるコードの変更箇所
変更されたファイルは `doc/go_spec.html` のみです。
```html
<pre><code>
const f = int32(1) << 33 // illegal (constant 8589934592 overflows int32)
</code></pre>
この行は、Go言語の仕様書内で定数宣言の例を説明しているセクションにあります。
コアとなるコードの解説
変更された行は、Go言語の仕様書における定数とビットシフト演算のセクションの一部です。
元の記述:
const f = int32(1) << 33 // f == 0 (type int32)
これは、int32
型の 1
を 33
ビット左シフトした結果が 0
になると誤って示していました。
修正後の記述:
const f = int32(1) << 33 // illegal (constant 8589934592 overflows int32)
この修正により、int32(1) << 33
という定数式が int32
の範囲を超過するため、コンパイル時に「illegal」(不正、エラー)となることが明確に示されました。コメントには、オーバーフローする具体的な値 8589934592
も記載されており、なぜ不正なのかがより分かりやすくなっています。
この変更は、Go言語の定数評価が、たとえシフト演算であっても、結果がターゲットの型に収まることを厳密に要求するという重要な側面を強調しています。これは、C言語などでのビットシフトの挙動(特にシフト量が型のビット幅を超える場合)とは異なるため、Go言語の正確な理解のために非常に重要な修正です。
関連リンク
- Go Issue #5430: https://github.com/golang/go/issues/5430
- Go Change List (CL) 9305043: https://golang.org/cl/9305043 (現在は
https://go.dev/cl/9305043
にリダイレクトされます) - The Go Programming Language Specification (Constants): https://go.dev/ref/spec#Constants
- The Go Programming Language Specification (Shift operators): https://go.dev/ref/spec#Shift_operators
参考にした情報源リンク
- Go言語の公式ドキュメント(特に仕様書)
- GitHub上のGoリポジトリのコミット履歴とIssueトラッカー
- Go言語の定数と型に関する一般的な知識