6

実行を遅らせることのみを目的とする ANSI C の while ループを考えてみましょう。

unsigned long counter = DELAY_COUNT;
while(counter--);

これが組み込みシステムに遅延を強制するために多く使用されているのを見てきました。機能はなくsleep、タイマーまたは割り込みは制限されています。

私の ANSI C 標準の解釈は、これは準拠するコンパイラによって完全に削除できるということです。5.1.2.3で説明されている副作用はありません。

揮発性オブジェクトへのアクセス、オブジェクトの変更、ファイルの変更、またはこれらの操作のいずれかを行う関数の呼び出しはすべて、実行環境の状態の変化である副作用です。

...そして、このセクションには次のようにも書かれています。

実際の実装では、式の値が使用されておらず、必要な副作用 (関数の呼び出しや揮発性オブジェクトへのアクセスによるものを含む) が生成されていないと推測できる場合、式の一部を評価する必要はありません。

これは、ループを最適化できることを意味しますか? counterだったとしてもvolatile

ノート:

  1. これは、「コンパイラーは無限ループを排除することを許可されていますか?」とまったく同じではありません。、それは無限ループを指し、プログラムがいつ終了できるかについて疑問が生じるためです。この場合、最適化の有無にかかわらず、プログラムは確実にこの行を越えて進みます。
  2. GCC が何をするかは知っていますが (-O1でない限り、 for 以上のループを削除しcounterますvolatile)、標準が何を指示しているかを知りたいです。
4

4 に答える 4

12

C 標準への準拠は、「as-if」ルールに従います。これにより、コンパイラは、抽象マシンで実際の命令を実行しているかのように動作するコードを生成できます。操作を実行しないと、ループを実行したかのように観察可能な動作が同じになるため、コードを生成しなくてもかまいません。

つまり、実際のマシンで何かを計算するのにかかる時間は、プログラムの「観察可能な」動作の一部ではなく、単に特定の実装の現象です。

volatilevolatile へのアクセスは「観察可能な」効果としてカウントされるため、変数の場合は状況が異なります。

于 2013-01-21T23:35:36.243 に答える
9

これは、ループを最適化できることを意味しますか?

はい。

カウンターが揮発性だったとしても?

いいえ。これは、監視可能な動作を持つ volatile 変数を読み書きするため、発生する必要があります。

于 2013-01-21T23:34:49.910 に答える
2

カウンターが の場合volatile、コンパイラは遅延ループを合法的に最適化できません。それ以外の場合は可能です。

このような遅延ループは、コンパイラがどのようにコードを生成するかによって燃焼時間が異なるため、良くありません。さまざまな最適化オプションを使用すると、さまざまな遅延を実現できますが、これは遅延ループからはほとんど望まれません。

このため、このような遅延ループは、プログラマがコードを完全に制御するアセンブリ言語で実装する必要があります。これは通常、単純な CPU を備えた組み込みシステムに適用されます。

于 2013-01-21T23:35:31.203 に答える
1

標準は、表示される動作を決定します。依存関係ツリーを作成すると、DELAY_COUNT使用しないで変更するプロパティがあることがわかります。これは、削除できることを意味します。これは、不揮発性ケースに関するものです。volatile の場合、コンパイラは依存関係ツリーを使用してこの変数を削除しようとすることができず、遅延が残ります (volatile は、ハードウェアがメモリにマップされた値を変更できることを意味するため、または場合によっては「これをスローしないで本当に必要な場合」を意味するため)揮発性とラベル付けされている場合は、コンパイラに伝えます。これを捨てないでください。理由があります。

于 2013-01-21T23:36:44.447 に答える