Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Data Types  ›  Lesson

Type Qualifiers

Type Qualifiers 14 minThe qualifiers const, volatile, restrict and _Atomic are promises about how a variable is accessed: never modified, possibly changed from outside, not aliased, or accessed indivisibly across threads.

Type Qualifiers

The logger has a maximum number of readings that must never change, a sensor register that changes on its own, and a counter shared by two threads. The type int says nothing about any of that. Type qualifiers add the missing promises, and the compiler holds you, and itself, to them.

The rule

Qualifiers are promises: const won't change, volatile might, restrict is alone.

const: the program will not modify it.

const int max_readings = 96;
max_readings = 100;               /* compile error: assignment to a const */

With pointers, the position of const matters. const char *label means the characters cannot be changed through label; char *const label means the pointer itself cannot be changed.

volatile: it may change outside the program's control. The compiler must perform every read and write exactly as written, instead of keeping a copy in a register. Use it for memory-mapped hardware registers and for flags set by a signal handler:

#include <signal.h>

volatile sig_atomic_t stop_requested = 0;   /* set by a signal handler */

restrict (C99): this pointer is the only way to reach that memory. It applies only to pointers. The programmer promises that while the pointer is in use, the object it points to is not also accessed through some other pointer, which lets the compiler optimise harder. memcpy declares its parameters restrict, which is why it must not be given overlapping buffers; memmove makes no such promise and handles overlap. Breaking a restrict promise is undefined behaviour.

void add_offset(size_t n, int *restrict out, const int *restrict in);

_Atomic (C11): every access is indivisible between threads. Include <stdatomic.h> for friendly names like atomic_int:

#include <stdatomic.h>

atomic_int readings_taken = 0;
/* in any thread: */
readings_taken++;                 /* one indivisible read-modify-write */

Atomics are an optional C11 feature; an implementation without them defines __STDC_NO_ATOMICS__. Note that volatile does not make an increment safe between threads. That job belongs to _Atomic or a mutex.

The shortcut

Turn each qualifier into a question about the variable:

  • Should nothing ever change it? const
  • Can something outside the program change it? volatile
  • Is this pointer the only route to its memory? restrict
  • Do several threads touch it at once? _Atomic
Qualifying the loggerStep 1 of 4
  1. The maximum

    Fixed at build time and never changed: const int max_readings = 96;.

Drills

Answer fast — trust the rule.

quick drill

Which qualifier suits a hardware status register that the sensor updates by itself?

quick drill

Two threads both increment readings_taken. Which qualifier makes each increment indivisible?

quick drill

What can restrict qualify?

quick drill

Which standard function has restrict parameters and must not be given overlapping buffers?

Remember

  • Qualifiers are promises: const won't change, volatile might, restrict is alone, and _Atomic is indivisible.
  • Shortcut: ask the four questions (never changes, changed from outside, only route, shared by threads).
  • Trap: volatile is not thread safety, and breaking a restrict promise is undefined behaviour.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainPromises in the logger

The logger has a fixed maximum number of readings, a hardware status register that the sensor updates on its own, and a readings counter shared by two threads. Choose a qualifier for each and explain what promise it makes.