Est-il suffisant de déclarer une instance d'une variable de type structure comme volatile (si ses champs sont accessibles en code rentrant), ou doit-on déclarer des champs spécifiques de la structure volatils?
Formulées différemment, quelles sont les différences sémantiques (le cas échéant) entre:
typdef struct {
uint8_t bar;
} foo_t;
volatile foo_t foo_inst;
et
typedef struct{
volatile uint8_t bar;
} foo_t;
foo_t foo_inst;
Je reconnais que déclarer une variable de type pointeur comme volatile (par exemple, uint8_t * foo volatile) informe simplement le compilateur que l'adresse pointée par foo peut changer, tout en ne faisant aucune déclaration sur les valeurs pointées par foo. Il n'est pas clair pour moi si une analogie est valable pour les variables de type structure.
Dans votre exemple, les deux sont identiques. Mais les problèmes tournent autour de pointeurs.
Tout d'abord, volatile uint8_t *foo;
indique au compilateur que la mémoire pointée est volatile. Si vous souhaitez marquer le pointeur lui-même comme volatile, vous devez faire uint8_t * volatile foo;
Et c'est là que vous obtenez les principales différences entre le marquage de la structure comme volatile et le marquage de champs individuels. Si tu avais:
typedef struct
{
uint8_t *field;
} foo;
volatile foo f;
Cela agirait comme:
typedef struct
{
uint8_t * volatile field;
} foo;
et pas comme:
typedef struct
{
volatile uint8_t *field;
} foo;
si vous déclarez une structure avec volatile, alors tous ses membres seront également volatils