C言語 の long int データ型仕様
概要
今回、開発環境でテストすると正しいが、本番環境では正しい結果が出力できなかった。
あまりにバカらしい理由ではあるが、戒めのために記述する。
起こった事
問題箇所
ある計算結果を出力するのだが、その結果は結構大きな値になってしまうので、
結果を格納するデータの型に long int を使用。そして、結果の表示において最初以下のように記述していた。
long int result = (計算部); printf("%d", result); // 588491482334(期待値)
すると、出力結果が明らかに小さい。
80962782
そして、自分が フォーマッタを『%d』にしていたミスに気付く。
『%d』→ 『%ld』に修正して、テスト。
long int result = (計算部); printf("%ld", result); // 588491482334(期待値)
出力結果が期待されるものになった。
588491482334
これで問題ないと思い、本番環境に送信して実行。その出力結果。
80962782
なぜか出力が戻った。送信したプログラムを確認したが問題ない。
問題解決フェーズ
計算結果を小さくしてみると正しい値が表示されるため、この現象は計算結果が大きくなった時のみ起こる。
しかし、フォーマッタは『%ld』を指定しているので、問題ないはずだが・・。
試しに『%lu』に変更してみたが効果なし。
今は C 言語の仕様が変わったのか?と思い、C 言語の仕様書を漁るもどこも変更なさそう。
仕方がないので本番環境で試しに、『LONG_MAX』(limits.h)を出力してみた。
2147483647
この瞬間、計算期待値がlong int の表現範囲を超えてることに気づく。
そこで、下記のように修正。
long long int result = (計算部); printf("%lld", result); // 588491482334(期待値)
本番環境でも動作を確認。こんな単純な問題に2時間掛けてしまった。
C 言語のデータ型仕様
この問題の要因を作った、long int の表現範囲を調べる。
まず、一般的には(データ型を参照)
int → 2byte(-32768~32767)を記憶できる
long int → 4byte (-2147483648~2147483647)を記憶できる
long long int → 8byte (-9223372036854775808~9223372036854775807)を記憶できる
まず、ここで既に勘違い。
long int が 8byte だと思ってた。(Java の long 型が 8byte だから)
(付け加えるなら long long int は 16byte だと思ってた)
そして、仕様は結構アバウトであり、基本的に下限だけ決まっている。
つまり、byte 数が大きい分には構わない。実際、私の開発環境では
#include<stdio.h> #include<limits.h> int main() { printf("INT_MAX:\t%d\n", INT_MAX); printf("LONG_MAX:\t%ld\n", LONG_MAX); printf("LLONG_MAX:\t%lld\n", LLONG_MAX); return 0; }
その結果。
INT_MAX: 2147483647 LONG_MAX: 9223372036854775807 LLONG_MAX: 9223372036854775807
long int は 8byte だった。しかも、 long long int とデータサイズ同じだった。
普段そんなに大きな値を使わないから、全く意識できていなかった。
反省。
結論
基本的なことではあるけれど、データ仕様は正しく覚える。
環境によってデータサイズが異なる事にも留意する。