要約: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
の動作に違いがあるかどうかを知りたいからです) 。
コードでは、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
が指しているオブジェクトを記述します。