volatile в C нужен не «для красоты», а чтобы компилятор не сломал работу с железом.Когда код читает memory-mapped IO регистр, значение может измениться не из-за программы, а из-за устройства.
Например:
#define STATUS_REG (*(volatile uint32_t*)0x40000000)
#define READY_BIT (1 << 0)
while (!(STATUS_REG & READY_BIT)) {
// ждём, пока железо станет ready
}
Без
volatile компилятор может решить:«Значение не меняется внутри цикла, значит можно прочитать один раз».
И всё. Опрос регистра превращается в бесконечный цикл или вообще оптимизируется не так, как вы ожидали.
Главная мысль:
volatile говорит компилятору:это значение может измениться вне твоего контроля, не трогай чтения и записи.
Важно:
volatile не заменяет mutex, atomics и memory barriers. Но для MMIO-регистров это база, без которой embedded-код может вести себя как магия из ада.
