Keeping a measurement loop
An empty loop can disappear during compilation because it has no effect. In `for (uint64_t volatile i = 0; i < iterations; ++i) { }`, the qualifier keeps accesses to `i` from being optimized away. That preserves a loop to measure, but it also changes what the measurement includes. section 15.3
TAKEAWAY: An access to a volatile object reloads its value from memory; a modification stores it to memory. The qualifier applies in a declaration like `unsigned volatile depth = 0`. It blocks optimizations that would otherwise make assumptions about that object's value, so use it only when needed. section 17.5
That cost matters in the loop example. GCC and Clang emit repeated loads and stores for the volatile counter. Keeping an ordinary counter and making only an assignment to an auxiliary object volatile produces a shorter loop; the measured version with that store was 80% faster than the volatile-counter version. Volatile preserves the intended accesses, not a negligible measurement overhead. section 15.3
Listing 15.6. Instrumenting three for loops with struct timespec
53 timespec_get(&t[0], TIME_UTC);
54 /* Volatile for i ensures that the loop is effected */
55 for (uint64_t volatile i = 0; i < iterations; ++i) {
56 /* do nothing */
57 }
58 timespec_get(&t[1], TIME_UTC);
59 /* s must be volatile to ensure that the loop is effected */
60 for (uint64_t i = 0; i < iterations; ++i) {
61 s = i;
62 }
63 timespec_get(&t[2], TIME_UTC);
64 /* Opaque computation ensures that the loop is effected */
65 for (uint64_t i = 1; accu0 < upper; i += 2) {
66 accu0 += i;
67 }
68 timespec_get(&t[3], TIME_UTC);
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":2}],[{\"line\":0,\"ch\":8},{\"line\":0,\"ch\":20}],[{\"line\":5,\"ch\":8},{\"line\":5,\"ch\":20}],[{\"line\":10,\"ch\":8},{\"line\":10,\"ch\":20}],[{\"line\":15,\"ch\":8},{\"line\":15,\"ch\":20}],[{\"line\":0,\"ch\":28},{\"line\":0,\"ch\":36}],[{\"line\":5,\"ch\":28},{\"line\":5,\"ch\":36}],[{\"line\":10,\"ch\":28},{\"line\":10,\"ch\":36}],[{\"line\":15,\"ch\":28},{\"line\":15,\"ch\":36}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":2}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":2}],[{\"line\":1,\"ch\":20},{\"line\":1,\"ch\":23}],[{\"line\":2,\"ch\":8},{\"line\":2,\"ch\":11}],[{\"line\":7,\"ch\":8},{\"line\":7,\"ch\":11}],[{\"line\":12,\"ch\":8},{\"line\":12,\"ch\":11}],[{\"line\":2,\"ch\":13},{\"line\":2,\"ch\":21}],[{\"line\":7,\"ch\":13},{\"line\":7,\"ch\":21}],[{\"line\":12,\"ch\":13},{\"line\":12,\"ch\":21}],[{\"line\":2,\"ch\":22},{\"line\":2,\"ch\":30}],[{\"line\":6,\"ch\":21},{\"line\":6,\"ch\":29}],[{\"line\":3,\"ch\":0},{\"line\":3,\"ch\":2}],[{\"line\":4,\"ch\":0},{\"line\":4,\"ch\":2}],[{\"line\":5,\"ch\":0},{\"line\":5,\"ch\":2}],[{\"line\":0,\"ch\":8},{\"line\":0,\"ch\":20}],[{\"line\":5,\"ch\":8},{\"line\":5,\"ch\":20}],[{\"line\":10,\"ch\":8},{\"line\":10,\"ch\":20}],[{\"line\":15,\"ch\":8},{\"line\":15,\"ch\":20}],[{\"line\":0,\"ch\":28},{\"line\":0,\"ch\":36}],[{\"line\":5,\"ch\":28},{\"line\":5,\"ch\":36}],[{\"line\":10,\"ch\":28},{\"line\":10,\"ch\":36}],[{\"line\":15,\"ch\":28},{\"line\":15,\"ch\":36}],[{\"line\":6,\"ch\":0},{\"line\":6,\"ch\":2}],[{\"line\":7,\"ch\":0},{\"line\":7,\"ch\":2}],[{\"line\":1,\"ch\":20},{\"line\":1,\"ch\":23}],[{\"line\":2,\"ch\":8},{\"line\":2,\"ch\":11}],[{\"line\":7,\"ch\":8},{\"line\":7,\"ch\":11}],[{\"line\":12,\"ch\":8},{\"line\":12,\"ch\":11}],[{\"line\":2,\"ch\":13},{\"line\":2,\"ch\":21}],[{\"line\":7,\"ch\":13},{\"line\":7,\"ch\":21}],[{\"line\":12,\"ch\":13},{\"line\":12,\"ch\":21}],[{\"line\":8,\"ch\":0},{\"line\":8,\"ch\":2}],[{\"line\":9,\"ch\":0},{\"line\":9,\"ch\":2}],[{\"line\":10,\"ch\":0},{\"line\":10,\"ch\":2}],[{\"line\":0,\"ch\":8},{\"line\":0,\"ch\":20}],[{\"line\":5,\"ch\":8},{\"line\":5,\"ch\":20}],[{\"line\":10,\"ch\":8},{\"line\":10,\"ch\":20}],[{\"line\":15,\"ch\":8},{\"line\":15,\"ch\":20}],[{\"line\":0,\"ch\":28},{\"line\":0,\"ch\":36}],[{\"line\":5,\"ch\":28},{\"line\":5,\"ch\":36}],[{\"line\":10,\"ch\":28},{\"line\":10,\"ch\":36}],[{\"line\":15,\"ch\":28},{\"line\":15,\"ch\":36}],[{\"line\":2,\"ch\":17},{\"line\":2,\"ch\":19}],[{\"line\":7,\"ch\":17},{\"line\":7,\"ch\":19}],[{\"line\":11,\"ch\":0},{\"line\":11,\"ch\":2}],[{\"line\":12,\"ch\":17},{\"line\":12,\"ch\":19}],[{\"line\":12,\"ch\":0},{\"line\":12,\"ch\":2}],[{\"line\":1,\"ch\":20},{\"line\":1,\"ch\":23}],[{\"line\":2,\"ch\":8},{\"line\":2,\"ch\":11}],[{\"line\":7,\"ch\":8},{\"line\":7,\"ch\":11}],[{\"line\":12,\"ch\":8},{\"line\":12,\"ch\":11}],[{\"line\":2,\"ch\":13},{\"line\":2,\"ch\":21}],[{\"line\":7,\"ch\":13},{\"line\":7,\"ch\":21}],[{\"line\":12,\"ch\":13},{\"line\":12,\"ch\":21}],[{\"line\":13,\"ch\":0},{\"line\":13,\"ch\":2}],[{\"line\":14,\"ch\":0},{\"line\":14,\"ch\":2}],[{\"line\":15,\"ch\":0},{\"line\":15,\"ch\":2}],[{\"line\":0,\"ch\":8},{\"line\":0,\"ch\":20}],[{\"line\":5,\"ch\":8},{\"line\":5,\"ch\":20}],[{\"line\":10,\"ch\":8},{\"line\":10,\"ch\":20}],[{\"line\":15,\"ch\":8},{\"line\":15,\"ch\":20}],[{\"line\":0,\"ch\":28},{\"line\":0,\"ch\":36}],[{\"line\":5,\"ch\":28},{\"line\":5,\"ch\":36}],[{\"line\":10,\"ch\":28},{\"line\":10,\"ch\":36}],[{\"line\":15,\"ch\":28},{\"line\":15,\"ch\":36}]]"}
!@%STYLE%@!
Compare the volatile counter, the ordinary counter with a volatile store, and the opaque computation. Each keeps a loop available for measurement by a different means. section 15.3
A value used after a long jump
A parser records nesting depth before an exceptional path returns through `longjmp`. If that depth was modified across the jump and is used afterward for a diagnostic, an ordinary declaration can let optimization assume the wrong value. Declaring it `unsigned volatile depth = 0` and updating the corresponding function parameter keeps the stored value available to the diagnostic. section 17.5
TAKEAWAY: Objects modified across `longjmp` must be volatile when their values are needed afterward. Signal handling presents another restricted use: an interrupt condition can be marked with a `volatile sig_atomic_t` flag, or with the listed atomic alternatives, for handling after the interrupted context resumes. section 17.5 section 17.7

