ごく普通のナル終端文字列”123″を整数値の123に変換するとき、あなたはどんな方法を用いるでしょうか? 学校の課題でもないかぎり、1文字ずつ取り出して数字かどうかを判別し、数字なら取り出した文字から’0’を引いた値を元の値に10倍したものに加えていく…といった処理をわざわざ書くことはないでしょう(組込み用途のフリースタンディング処理系やライブラリ自体の開発の場合は別ですが)。

上記のような変換を行う場合、atoi関数を使っていることが少なくないと思います。しかし、本当にそれでよいのでしょうか? atoi関数というのは、元の文字列が正しい書式で、しかもオーバーフローが起きない場合にのみ正しく動作します。そうでない場合、エラー検出を行うことがまったくできません。特に、オーバーフロー発生時には未定義の動作を引き起こします。こんな危険な関数を使ってよいはずがありません。

この問題を回避するためには、strtol関数を使います。long型ではなくint型に変換する場合であってもstrtol関数を使います。strtol関数以外の選択肢を強いて挙げるなら、スクラッチで記述するか、C++であれば、std::istringstreamやstd::istrstreamあるいはboost::lexical_castを使うかということになります。C++11以降であればstoi関数を使うこともできるでしょう。

では、atoi関数はまったく使えないかというとそんなことはありません。ちょっとした使い捨てプログラムなどで、atoi関数に与える文字列を自分で完全に管理できるような場合には、atoi関数を使っても問題はありません。その意味では gets関数と同じではないかと思います。

あるいは、外部からの入力ではなく、内部的に生成した安全な文字列しか atoi には与えないということであれば、atoi関数の方が優れていることもあります。エラーチェックがなく、10進数しか扱えない分、atoi関数の方がstrtol関数より軽量であることは間違いありません。また、組込み向けの処理系など、int型が16ビットの場合には、long型を扱うstrtol関数よりatoi関数の方が劇的にパフォーマンスが高くなるということもあり得ます。

逆にいえば、こうした状況以外で atoi関数の出番は一切ありません。それは、atof関数についてもほぼ同じことがいえます(atof関数の方がさらに出番は少ないでしょう)。