次のコードがあるとします。
my_struct_member_type *foo() {
volatile my_struct *s = (my_struct *)SOME_ADDRESS;
return &(s->struct_member);
}
fooによって返されるポインタも揮発性ですか?
編集:フォローアップ:ポインター&(s->struct_member)
はfoo内で揮発性ですか?
No.volatile
はコンパイラのヒントであり、コンパイラがそれを認識できる場合にのみ尊重されます。volatile
その関数は、最初にポインタを宣言することを知らない別の変換ユニットから呼び出すことができます。
はい。
Forvolatile my_struct *s
は、それを通して見るオブジェクトはでvolatile
あり、このポインターを介してアクセスするすべてのメンバーはvolatile
資格を継承すると言います。
volatile
戻り型がそう言っていない場合に返されるポインタのアドレスを持つことは制約違反であり、コンパイラはその診断を提供している必要があります。
編集:volatile
キーワードが適用される場所にも混乱があるようです。あなたの例では、それはポインタ自体ではなく、ポイントされたオブジェクトに適用されます。経験則として、タイプを変更せずに、常に修飾子(const
またはvolatile
)をできるだけ右側に記述します。次に、あなたの例は次のようになります。
my_struct volatile*s = (my_struct *)SOME_ADDRESS;
これは完全に異なります
my_struct *volatile s = (my_struct *)SOME_ADDRESS;
ここで、ポインタ自体はありますvolatile
が、その背後にあるオブジェクトではありません。
編集2:あなたが私の情報源、実際のC標準、C11、6.8.6.4を求めているので、それはreturn
ステートメントについて述べています:
式の型が、それが表示される関数の戻り型と異なる場合、値は、関数の戻り型を持つオブジェクトに割り当てられたかのように変換されます。
したがって、代入演算子の6.15.16.1は、変換から期待されるものです。
左側のオペランドには、アトミック、修飾、または非修飾のポインター型があり、(左オペランドが左辺値変換後に持つ型を考慮すると)両方のオペランドは、互換性のある型の修飾または非修飾バージョンへのポインターであり、左側が指す型にはすべてがあります。右が指すタイプの修飾子。
ここで、右側の尖ったタイプには、左側のタイプに加えてvolatile
修飾子があります。
Volatileは実行時に意味がなく、変数へのアクセスを最適化しないようにコンパイラーに指示するために使用されます。
揮発性ポインタを返すことは意味がありません。一部のストレージ(左辺値)を右辺値ではなく揮発性としてマークします。
http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword