Qualifiers add promises about an object: const — I won’t write it; volatile — it may change behind the compiler’s back; restrict — this pointer is the only way to reach that memory.
| Qualifier | Promise / meaning | Typical use |
|---|---|---|
const | Not modified through this name | Read-only parameters, lookup tables |
volatile | Every read and write must really happen, in order — no caching in registers | Memory-mapped hardware registers, variables changed by signal handlers |
restrict (C99) | For the pointer’s lifetime, the object is accessed only through it | memcpy, numeric kernels — enables vectorisation |
_Atomic (C11) | Accesses are atomic | Lock-free counters shared between threads |
volatile
#include <stdio.h>
#include <signal.h>
static volatile sig_atomic_t stop = 0; /* changed by a signal handler */
void on_signal(int sig) { (void)sig; stop = 1; }
int main(void) {
signal(SIGINT, on_signal);
long spins = 0;
while (!stop) { /* volatile: re-read every iteration */
if (++spins == 1000000) raise(SIGINT);
}
printf("stopped after %ld spins\n", spins);
return 0;
}stopped after 1000000 spinsrestrict
#include <stdio.h>
/* the caller promises dst and src do not overlap, so the compiler may vectorise */
void add_arrays(size_t n, float *restrict dst, const float *restrict src) {
for (size_t i = 0; i < n; i++) dst[i] += src[i];
}
int main(void) {
float a[4] = {1, 2, 3, 4}, b[4] = {10, 20, 30, 40};
add_arrays(4, a, b);
printf("%.0f %.0f %.0f %.0f\n", a[0], a[1], a[2], a[3]);
return 0;
}11 22 33 44The standard library uses it: void *memcpy(void *restrict dst, const void *restrict src, size_t n); — which is precisely why overlapping memcpy is undefined and memmove (no restrict) exists.
Can a variable be both const and volatile?
What happens if you break a restrict promise?