[迷信] 文字列から整数への変換には 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:

http://www.kijineko.co.jp/trackback/508
このエントリーを含むはてなブックマーク