構造型変数のインスタンスをvolatileとして宣言するだけで十分ですか(そのフィールドがリエントラントコードでアクセスされる場合)、または構造の特定のフィールドをvolatileとして宣言する必要がありますか?
別の言い方をすると、以下のセマンティックの違い(ある場合)は何ですか?
typdef struct {
uint8_t bar;
} foo_t;
volatile foo_t foo_inst;
そして
typedef struct{
volatile uint8_t bar;
} foo_t;
foo_t foo_inst;
ポインター型変数をvolatile(たとえばvolatile uint8_t * foo)として宣言することは、fooが指す値に関するステートメントを作成せずに、fooが指すアドレスが変更される可能性があることをコンパイラーに単に通知することを認識しています。構造型変数について類推が当てはまるかどうかはわかりません。
あなたの例では、2つは同じです。しかし、問題はポインターを中心に展開します。
最初に、 volatile uint8_t *foo;
は、指すメモリが揮発性であることをコンパイラに伝えます。ポインター自体をvolatileとしてマークする場合は、uint8_t * volatile foo;
そして、構造体を揮発性としてマークすることと個々のフィールドをマークすることの主な違いに到達します。あなたが持っていた場合:
typedef struct
{
uint8_t *field;
} foo;
volatile foo f;
それは次のように振る舞います:
typedef struct
{
uint8_t * volatile field;
} foo;
好きではない:
typedef struct
{
volatile uint8_t *field;
} foo;
volatileを持つ構造体を宣言すると、そのすべてのメンバーもvolatileになります