int型の最大値に1を足すと最小値(負の数)に折り返る
INT_MAXに1を足すと、多くの環境ではINT_MINまで折り返り、突然大きな正の数が大きな負の数に変わります。
なぜエラーが出ないのか
出力: -2147483648
(エラーなし)- Cは何も報告しません。コンパイルも実行も正常に完了するためです
出力: -2147483648- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 #include <limits.h> 2 #include <stdio.h> 3 4 int main(void) { 5 int x = INT_MAX; 6 long y = (int )x + 1; ^ 7 printf("%ld\n", y); 8 return 0; 9 }
出力: -2147483648期待: 2147483648
(int)x + 1はint型のまま加算されるため、INT_MAXを超えた瞬間に折り返り負の数になります。longにキャストしてから足せば、加算そのものがlong型で行われるため折り返りません。
直し方: int を long にします。
広告
広告スロット(未設定)
パターン2
1 #include <limits.h> 2 #include <stdio.h> 3 4 int main(void) { 5 int count = INT_MAX - 1; 6 long total = (int )count + 3; ^ 7 printf("%ld\n", total); 8 return 0; 9 }
出力: -2147483647期待: 2147483649
countがINT_MAXに近い値の場合、3を足しただけでも簡単にオーバーフローします。加算前にlongへ広げておくことが対策になります。
直し方: int を long にします。
パターン3
1 #include <limits.h> 2 #include <stdio.h> 3 4 int main(void) { 5 int stock = INT_MAX; 6 long updated = (int )stock + 100; ^ 7 printf("%ld\n", updated); 8 return 0; 9 }
出力: -2147483549期待: 2147483747
在庫数や合計値を数える変数の型が小さすぎると、長時間動作するプログラムで突然この種のオーバーフローが発生します。
直し方: int を long にします。
よくある誤解
エラーにも警告にもなりません。C言語の符号付き整数のオーバーフローは未定義動作と定義されていますが、多くのコンパイラ・環境では実質的に2の補数表現に基づいてビットがそのまま折り返ります。合計値や個数を数える変数の型が小さすぎると、長時間動作するプログラムで突然発生することがあります。
まとめ
int型の最大値に1を足すと最小値(負の数)に折り返るは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。