おい俺のgcc 一体エラー処理はどこまで書けばいいんだいっ

公開:2020/10/06
更新:2020/10/06
2 min読了の目安(約2200字TECH技術記事

結論

コンパイラがエラーを出してくれる入力に対しては、関数の中で処理を書く必要はない。
エラーを出してくれないかつ例外として扱いたい入力に対してだけ処理を書いてあげよう。

事の始まり

例えば与えられた引数番目のフィボナッチ数列の値を返す関数を作りたいとする。
ここではフィボナッチ数列の0番目の値が0 1番目の値が1と考えて、コードをこんなふうに書いたとしよう。

int	fibonacci(int n)
{
    if (n == 0)
        return (0);
    if (n == 1)
        return (1);
    return (fibonacci(n - 1) + fibonacci(n - 2));
}

こいつをmainから呼び出してやればn番目の値が返ってくる。

しかしプログラマーたるもの常に例外というものを考えてやらねばならない。
引数のデータ型をintとはしているものの、intの範囲外の入力が与えられる可能性もあるわけである。
C言語においてintの最小値は-2147483648 最大値は2147483647。
つまりはこんな風に呼び出される可能性が考えられる。

int    main(void)
{
    fibonacci(7777777777);
    fibonacci(-9999999999);
}

知っている。gccはなんでも知っている。

コンパイルを行う前にその可能性に気が付き、nがintの範囲外である場合を考慮したコードを追加したとする。

int	fibonacci(int n)
{
    if (n < -2147483648 || n > 2147483647)
        return (-1);
    if (n == 0)
        return (0);
    if (n == 1)
        return (1);
    return (fibonacci(n - 1) + fibonacci(n - 2));
}

よし。これでintの範囲外の値が引数で与えられても大丈夫なはずだ。
いざコンパイル。

Screen Shot 2020-10-06 at 22.54.59.png

この通りである。

画像にあるように、int型の引数に対してintの最小値より小さい値もしくは最大値よりも大きい値を渡そうとするとコンパイラがエラーを出してくれる。
(intがlongに黙示的に変換されてどうのこうの言っている。ここでは気にしなくてよい。)

そしてコンパイルエラーが起きているので実行可能ファイル(a.out)は作成されていない。

日の目を見ることのない条件式

つまり下のif文は永久に実行されないことになる。

    if (n < -2147483648 || n > 2147483647)
        return (-1);

であるならわざわざこの条件式を書く必要はない。

コンパイラがエラーを出してくれるおかげで、いちいち引数がintの最小値より小さいとか最大値より大きいとかを気にしなくて済むわけである。
なんともありがたい話だ。

書くべき例外処理

ここまででコンパイラがエラーを出してくれる値については処理を書かなくても済むことがわかった。
裏を返せばコンパイラがエラーを出してくれない値については例外的に処理を書く必要があるかもしれないということである。

先のフィボナッチ数列の関数であればnが負の場合について処理を書く必要がありそうだ。

int	fibonacci(int n)
{
    if (n < 0)
        return (-1);
    if (n == 0)
        return (0);
    if (n == 1)
        return (1);
    return (fibonacci(n - 1) + fibonacci(n - 2));
}

いまフィボナッチ数列を数列の0番目に0 1番目に1を与えて、2番目からは前の2項の和を値としてもつと考えていた。
1番目に1 2番目に1と考えてもよい。
どちらにせよ例えば-1番目のフィボナッチ数列の値は存在しない。

ここでfibonacci.cに引数として-1が渡される可能性は考慮すべき値となる。
なぜなら-1はintが扱う値の範囲内であり、コンパイラがエラーを出してくれないからである。

仕方がないので自分で処理を書かなければならない。
ということで上のif文を書くハメになるわけである。

筋肉は裏切らない

結論は最初に書いた通りだ。
自作関数のテストを考えているときに、ふとどこまで考えればいいのかと思って気づいたことをまとめた次第である。
それでは。

パワー!

ハッ。