[迷信] 文字列から整数への変換には atoi

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

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

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

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

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

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

トラックバック


URL から "-nospam" を削除してトラックバックを送信してください。
このエントリーを含むはてなブックマーク