Site Tools


c-volatile-qualifier

C volatile qualifier

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.

Example

// 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;
}

Common patterns

When to use volatile:

  • Hardware registers (memory-mapped I/O)
  • Shared memory with other processes/threads
  • Signal handler variables (use sig_atomic_t)
  • Variables modified by external code

Semantics:

  • Compiler reads/writes every access (no caching)
  • No optimization across volatile accesses
  • Guarantees ordering with respect to volatile

Not a substitute for:

  • Locks (doesn't prevent race conditions)
  • Atomic operations (not atomic)
  • Synchronization (use mutexes, atomics)

Signal handlers:

  • Only volatile sig_atomic_t is safe in handlers
  • Even volatile int not sufficient for signals
  • sig_atomic_t guaranteed atomic signal-safe access

Optimization prevention:

  • Compiler assumes non-volatile can be cached
  • Volatile forces memory access each time
  • Performance cost: prevents useful optimizations

Modern alternatives:

  • _Atomic (C11) for thread-safe atomics
  • volatile _Atomic for signal handlers + threading
  • Mutexes for shared memory (C threads)
c-volatile-qualifier.md · Last modified: by 127.0.0.1