Для базового типа:
volatile unit32_t *number; //The number pointed at is volatile
uint32_t *volatile number; //The pointer is volatile
volatile uint32_t number; //The number is volatile
Для структуры:
volatile struct_t *struct_p; //The members of the struct pointed at are volatile
struct_t *volatile struct_p; //The pointer is volatile
volatile struct_t struct_o; //The members of the struct are volatile
Конечно, их можно комбинировать:
volatile uint32_t *volatile number; //Both the pointer and the number are volatile
Надеюсь, теперь вы видитеобразец того, что делает модификатор volatile в зависимости от позиции.
Я не использовал volatile таким образом:
uint32_t volatile number; //I assume it will mean that the number is volatile
uint32_t volatile *number; //I assume it will mean that the number is volatile
Правило большого пальца заключается в том, что если модификатор volatile находится за * (указатель), он изменяет указатель, а не указанную переменную.
Для значения volatile сам по себе это означает, что компилятор не может ничего предположить о том, какие данные могут храниться в переменной, и, следовательно, не может оптимизировать любые операции над переменной.