17

概要volatile: CおよびC ++の関数宣言に適用すると 、キーワードは何をしますか?

詳細

としてマークされている関数をコンパイルできることがわかりますvolatile。ただし、これによってどのコンパイラ最適化が妨げられるか(ある場合)はわかりません。たとえば、次のテストケースを作成しました。

volatile int foo() {
  return 1;
}

int main() {
  int total = 0;
  int i = 0;
  for(i = 0; i < 100; i++) {
    total += foo();
  }

  return total;
}

でコンパイルするとclang -emit-llvm -S -O3 test.c(gccも機能しますが、私の意見ではllvm IRの方が読みやすいです)、次のようになります。

target triple = "x86_64-unknown-linux-gnu"

define i32 @foo() #0 {
  ret i32 1
}

define i32 @main() #0 {
  ret i32 100
}

したがって、コンパイラは、としてマークされている場合でも定数を返すfoo()ように、関数の呼び出しを最適化することができたのは明らかです。だから私の質問は、コンパイラの最適化を制限するという観点から、関数宣言に適用されたときに何かをするかどうかです。main()foo()volatilevolatile

(この質問への私の関心は、volatile特定の問題を解決するのではなく、何をするのかを理解することへの好奇心であることに注意してください。)

(また、この質問をCとC ++の両方としてマークしたのは、それらが同じ言語であると思うからではなくvolatile、この2つの言語でこの場合の動作に違いがあるかどうかを知りたいからです)。

4

2 に答える 2

27

コードでは、volatileキーワードは関数には適用されませんが、戻り値のタイプには、次と同等です。

typedef volatile int Type;
Type foo();

これで、C ++では、修飾子と同じ方法でメンバー関数を作成でき、動作は同じです。volatileconst

struct test {
   void vfunction() volatile;
};

基本的に、次のタイプの揮発性(それぞれconst)インスタンスで不揮発性(または非const)関数を呼び出すことはできません。

struct test {
   void vfunction() volatile;
   void function();
};
volatile test t;
t.vfunction();      // ok
t.function();       // error
于 2013-03-07T23:08:15.110 に答える
5

foo()揮発性ではありません。

を返す関数ですvolatile int

これは合法です。しかし、戻ってきたのは奇妙ですint

一方、メンバー関数はvolatile、同じ理由で使用できます。constどちらも、オブジェクトthisが指していることを表します。

于 2013-03-07T23:08:14.813 に答える