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

同カテゴリーの次の記事

インテル® Xeon® スケーラブル・プロセッサーのインテル® AVX-512 のベクトル長の拡張機能

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


18. ある言語の知識は必ずしも別の言語に適用できるとは限らない

Putty プロジェクトから抜粋した以下のコードについて考えてみます。非効率的なコードは、次の PVS-Studio 診断によって検出されます。

V814 Decreased performance. Calls to the ‘strlen’ function have being made multiple times when a condition for the loop’s continuation was calculated. (V814 パフォーマンス低下。ループの継続条件の計算時に ‘strlen’ 関数が複数回呼び出されました。)

static void tell_str(FILE * stream, char *str)
{
  unsigned int i;
  for (i = 0; i < strlen(str); ++i)
    tell_char(stream, str[i]);
}

説明

これは実際にはエラーではありませんが、strlen() 関数がループの各反復で呼び出されているため、長い文字列を扱う場合には非常に非効率的です。

通常、このようなエラーは、Pascal (または Delphi) での開発経験があるプログラマーが記述したコードで見られます。Pascal では、ループの終了条件の評価が一度しか計算されないため、このようなコードが非常に一般的です。

Pascal コードの例を見てみましょう。pstrlen() が一度だけ呼び出されているため、called は一度だけ出力されます。

program test;
var
  i   : integer;
  str : string;

function pstrlen(str : string): integer;
begin
  writeln('called');
  pstrlen := Length(str);
end;

begin
  str := 'a pascal string';
  for i:= 1 to pstrlen(str) do 
    writeln(str[i]);
end.

効率良いコード

static void tell_str(FILE * stream, char *str)
{
  size_t i;
  const size_t len = strlen(str);
  for (i = 0; i < len; ++i)
    tell_char(stream, str[i]);
}

推奨事項

C/C++ では、ループの終了条件が各反復で再計算されます。そのため、非効率な遅い関数の呼び出しを終了判定に含めることは、特にループに入る前にそれを一度計算すれば済む場合、良いアイデアとは言えません。

一部のケースでは、コンパイラーはこのような strlen() を含むコードを最適化できる可能性があります。例えば、ポインターが常に同じ文字列リテラルを参照する場合などです。しかし、それを期待すべきではありません。

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

関連記事

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