プログラミング、リファクタリング、そしてすべてにおける究極の疑問: No. 21

同カテゴリーの次の記事

プログラミング、リファクタリング、そしてすべてにおける究極の疑問: No. 22

この記事は、インテル® デベロッパー・ゾーンに公開されている「The Ultimate Question of Programming, Refactoring, and Everything」の日本語参考訳です。


21. ファイル終了文字 (EOF) に正しく到達したかチェックする

引き続き、ファイルの操作と EOF について見ていきましょう。ただし、これは全く異なる種類の問題です。通常、ソフトウェアのローカライズ版で発生します。

Computational Network Toolkit プロジェクトから抜粋した以下のコードについて考えてみます。このエラーは、次の PVS-Studio 診断によって検出されます。

V739 EOF should not be compared with a value of the ‘char’ type. The ‘c’ should be of the ‘int’ type. (V739 EOF は ‘char’ 型の値と比較すべきではありません。’c’ は ‘int’ 型であるべきです。)

string fgetstring(FILE* f)
{
  string res;
  for (;;)
  {
    char c = (char) fgetc(f);
    if (c == EOF)
      RuntimeError("error reading .... 0: %s", strerror(errno));
    if (c == 0)
      break;
    res.push_back(c);
  }
  return res;
}

説明

EOF は次のように定義されています。

#define EOF (-1)

つまり、EOF は int 型の ‘-1’ です。Fgetc() 関数は、int 型の値を返します。具体的には、0 から 255 の範囲の値か、-1 (EOF) を返します。読み取られた値は、char 型の変数に格納されます。このため、値 0xFF (255) の記号は -1 になり、ファイルの終わり (EOF) と同様に処理されます。

拡張 ASCII コードを使用する場合、プログラムが文字記号を正しく処理できないと、エラーになります。

例えば、Windows* 1251 コードページでは、ロシア語の最後のアルファベット文字に含まれる 0xFF コードが、プログラムによってファイル終了文字として解釈されます。

正しいコード

for (;;)
{
  int c = fgetc(f);
  if (c == EOF)
    RuntimeError("error reading .... 0: %s", strerror(errno));
  if (c == 0)
    break;
  res.push_back(static_cast<char>(c));
}

推奨事項

ここでは特に推奨事項はありませんが、EOF に関して広く認識されていない興味深いエラーを紹介したいと思います。

関数が int 型を返す場合、すぐに char 型に変更すべきではないことを覚えておいてください。まず、問題がないことを確認する必要があります。ところで、これと似た memcmp() のケースについては、すでに「2. 0 よりも大きいは 1 を意味しない」で述べました (同セクションの MySQL* のコード例を参照してください)。

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事

  • Parallel Universe マガジンParallel Universe マガジン Parallel Universe へようこそ。 米国インテル社が四半期に一度オンラインで公開しているオンラインマガジンです。インテルの技術者によるテクノロジーの解説や、最新ツールの紹介など、並列化に関する記事を毎号掲載しています。第1号からのバックナンバーを PDF 形式で用意しました、ぜひご覧ください。 12 […]
  • 比較関数の罠比較関数の罠 この記事は、インテル® デベロッパー・ゾーンに公開されている「The Evil within the Comparison Functions」の日本語参考訳です。 この記事の PDF […]
  • ファクトシート: oneAPIファクトシート: oneAPI この記事は、インテル ニュースルームに公開されている「Fact Sheet: oneAPI」の日本語参考訳です。 この記事の PDF 版はこちらからご利用になれます。 oneAPI とは? oneAPI […]
  • 並列プログラミングにおけるロックの効率的な使用並列プログラミングにおけるロックの効率的な使用 この記事は、インテル® ソフトウェア・ネットワークに掲載されている「Using Locks Effectively in Parallel Programming […]
  • インテル® IPP サンプル – エラーの修正インテル® IPP サンプル – エラーの修正 この記事は、インテル® ソフトウェア・ネットワークに掲載されている「Intel IPP Samples for Windows - error correction」の日本語参考訳です。 この記事は、PVS-Studio を使用することでプログラムがどのように安全になるかを説明した記事の 1 […]