Code Fix

中級

整数のオーバーフローが例外にならない理由

int型の範囲(約-21億〜21億)を超える計算をしても、既定では例外にならず値が折り返ります。

なぜエラーが出ないのか

出力: -2147483648
(エラーなし)
C#は何も報告しません。文法として正しいためです
出力: -2147483648
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  class Program {
 2      static void Main(string[] args) {
 3          int max = int.MaxValue;
 4          int result = max + 1 ;
                                ^
 5          System.Console.WriteLine(result);
 6      }
 7  }
出力: -2147483648

intの範囲は約21億までです。それを超えると例外にはならず、静かに最小値側へ折り返します(既定のuncheckedコンテキストのため)。

直し方: 1 を 0 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  class Program {
 2      static void Main(string[] args) {
 3          int max = int.MaxValue;
 4          int result = max * 2 ;
                                ^
 5          System.Console.WriteLine(result);
 6      }
 7  }
出力: -2

掛け算でも同じことが起きます。桁あふれは例外を投げず、そのまま計算を続けてしまいます。

直し方: 2 を 1 にします。

この問題を解いてみる →

パターン3

 1  class Program {
 2      static void Main(string[] args) {
 3          int min = int.MinValue;
 4          int result = min - 1 ;
                                ^
 5          System.Console.WriteLine(result);
 6      }
 7  }
出力: 2147483647

下限を下回る場合も同様に、例外を出さず上限側へ折り返します。checked演算子を使うと検出できます。

直し方: 1 を 0 にします。

この問題を解いてみる →

パターン4

 1  class Program {
 2      static void Main(string[] args) {
 3          int max = int.MaxValue;
 4          int result = max + 2 ;
                                ^
 5          System.Console.WriteLine(result);
 6      }
 7  }
出力: -2147483647

intの範囲を超えると例外にならず、静かに折り返ります。

直し方: 2 を 0 にします。

この問題を解いてみる →

パターン5

 1  class Program {
 2      static void Main(string[] args) {
 3          int max = int.MaxValue;
 4          int result = max * 3 ;
                                ^
 5          System.Console.WriteLine(result);
 6      }
 7  }
出力: 2147483645

掛け算でも同じことが起きます。桁あふれは例外を投げず計算を続けてしまいます。

直し方: 3 を 1 にします。

この問題を解いてみる →

よくある誤解

「範囲を超えたら止まってくれる」という期待は誤りです。C#は既定でuncheckedという文脈で動作するため、オーバーフローを検出したい場合はcheckedを明示する必要があります。

実務での勘所

checkedは文のブロック(checked { ... })としてだけでなく、checked(a + b)のように式単位でも書けます。さらにプロジェクト全体の既定を変える設定もあり、プロジェクトファイルにCheckForOverflowUnderflowをtrueに設定すると、明示的にcheckedと書かなくてもプロジェクト全体の算術演算がオーバーフロー検出付きになります。個々の式、ブロック、プロジェクト全体という3段階の粒度で、検出するかどうかを選べます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)