1

C標準は言う

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

volatile変数が必要ないのはいつですか? このパラグラフによれば、volatileは、他の非volatileオブジェクトと同様に as-if ルールの対象になるように見えます。


重複していないリンクされた質問で与えられた回答は、上記の引用された段落に対処していないため、私には役に立ちません

  • 値が「使用済み」と見なされるのはいつですか? 上記の引用によると、対応するアクセスを省略できるため、「オブジェクトから値を読み取る」とは異なるようです。
  • 「必要な副作用」とは何ですか?

以下のコメントを参照してください。

4

5 に答える 5

1

彼らはおそらく次のような状況を指していると思います

void test(int volatile *y)
{
    int x = *y;
}

int main(void)
{
    test(some_volatile_y);
    return 0;
}

メモリからの負荷を最適化して (評価せずに) 取り除くことができます。これは、その結果がすべての実装で必ずしも必要であるとは限らないためです。(もちろん、メモリ負荷が何らかのイベントをトリガーできる実装では、もちろん結果は「必要」であり、最適化して取り除くことはできません。)


C 標準のこの脚注を指摘してくれた以下の Alex のコメントに感謝します (C99: 6.7.3 型修飾子: 脚注 114):

volatile 宣言は、メモリ マップド入出力ポートに対応するオブジェクト、または非同期割り込み関数によってアクセスされるオブジェクトを記述するために使用できます。そのように宣言されたオブジェクトに対するアクションは、式を評価するための規則で許可されている場合を除き、実装によって「最適化」されたり、並べ替えられたりしてはなりません。

それはかもしれないと言っていることに注意してください- それは例を示しています。J.3 節では、volatile 修飾された型を持つオブジェクトへのアクセスを構成するものは実装定義であると述べています。それ以外は実装に依存します。

そのため、これが必要な副作用を引き起こす可能性がないことをシステムが認識している実装では、揮発性アクセスが削除される場合があります。

于 2013-04-20T09:51:00.843 に答える
1

標準的な意図のこの部分は、次のコードの揮発性読み取りが評価されないため削除できることを示しています。

volatile a;
if (0 && a) something();

ただし、次の揮発性読み取りではありません

volatile a;
int b;
b = 0*a;

mehrdad の回答に関する議論のフォローアップとして: J.3.10

J.3 実装定義の動作

J.3.10 修飾子

— volatile 修飾された型を持つオブジェクトへのアクセスを構成するもの (6.7.3)。

つまり、コンパイラはvolatileアクセスを無意味に定義できるため、基本的にそれを無視できます。もちろん、シグナルを実装することもできませんが、非同期シグナルの存在を無視することはできます。無視できないvolatileのは の周りだけlongjmpです。

もちろん、このような選択をすると、このコンパイラは本格的なシステム開発には役に立たなくなりますが、一部のアプリケーションではそれを必要とせず、標準では、そのような単純なアーキテクチャとそのアプリケーションに対して準拠した実装を許可しています。

于 2013-04-20T09:44:44.417 に答える
0

揮発性変数が必要ないのはいつですか?

5.1.2.3p4 を誤解しているようです。コンパイラが次の両方を証明できる場合、式を最適化して取り除くことができます。

  1. その値は使用されません。
  2. 必要な副作用は発生しません (関数の呼び出しや揮発性オブジェクトへのアクセスによるものを含む)。

要約すると、コンパイラは揮発性オブジェクトにアクセスする式を最適化できません。


コンパイラは、揮発性アクセスに副作用が必要かどうかを判断しますか?

標準はそれを決定し、コンパイラは適合する実装であることによって決定します。5.1.2.3p6: volatile オブジェクトへのアクセスは、抽象マシンの規則に従って厳密に評価されます。

于 2013-04-20T10:44:01.283 に答える