C volatile qualifier tells the compiler to never optimize away memory accesses. Declare as volatile int x to prevent caching in registers. Used for hardware registers, shared memory, signal handlers, or any data that can change outside program control.
Use volatile for hardware-mapped memory, global state accessed by signal handlers, or data shared with other code.
// compile: gcc -o volatile volatile.c // run: ./volatile // description: volatile for hardware and signal access #include <stdio.h> #include <signal.h> #include <unistd.h> volatile sig_atomic_t flag = 0; void signal_handler(int sig) { flag = 1; } // Hardware register (simulated) volatile int *hardware_reg = (volatile int *)0x12345678; int main() { signal(SIGUSR1, signal_handler); printf("Waiting for signal (send SIGUSR1 to PID %d)\n", getpid()); // Without volatile: compiler might cache flag in register // With volatile: every access reads from memory int iterations = 0; while (!flag && iterations < 1000000) { iterations++; } if (flag) { printf("Signal received after %d iterations\n", iterations); } else { printf("No signal (timeout)\n"); } return 0; }
When to use volatile:
sig_atomic_t)Semantics:
Not a substitute for:
Signal handlers:
volatile sig_atomic_t is safe in handlersvolatile int not sufficient for signalssig_atomic_t guaranteed atomic signal-safe accessOptimization prevention:
Modern alternatives:
_Atomic (C11) for thread-safe atomicsvolatile _Atomic for signal handlers + threading