web-dev-qa-db-ja.com

揮発性機能

要約:CおよびC++の関数宣言に適用された場合、キーワードvolatileは何をしますか?

詳細

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

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

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

16

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

typedef volatile int Type;
Type foo();

これで、C++では、volatile修飾子と同じ方法で、member関数constを作成でき、動作は同じです。

struct test {
   void vfunction() volatile;
};

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

struct test {
   void vfunction() volatile;
   void function();
};
volatile test t;
t.vfunction();      // ok
t.function();       // error

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

volatile intを返す関数です。

これは合法です。しかし、返されたintには奇妙です。

一方、メンバー関数は、volatileである可能性があるのと同じ理由で、constである可能性があります。どちらもthisが指しているオブジェクトを記述します。

5
Drew Dormann