Type qualifiers are the keywords which describe additional semantics about a type. They are an integral part of type signatures. They can appear both at the topmost level of a declaration (directly affecting the identifier) or at sub-levels (relevant to pointers only, affecting the pointed-to values):
Keyword | Remarks |
---|---|
const | Prevents the mutation of the declared object (by appearing at the topmost level) or prevents the mutation of the pointed-to value (by appearing next to a pointer subtype). |
volatile | Informs the compiler that the declared object (at topmost level) or the pointed-to value (in pointer subtypes) may change its value as a result of external conditions, not only as a result of program control flow. |
restrict | An optimization hint, relevant to pointers only. Declares intent that for the lifetime of the pointer, no other pointers will be used to access the same pointed-to object. |
The ordering of type qualifiers with respect to storage class specifiers (static
, extern
, auto
, register
), type modifiers (signed
, unsigned
, short
, long
) and type specifiers (int
, char
, double
, etc.) is not enforced, but the good practice is to put them in the aforementioned order:
static const volatile unsigned long int a = 5; /* good practice */
unsigned volatile long static int const b = 5; /* bad practice */
/* "a" cannot be mutated by the program but can change as a result of external conditions */
const volatile int a = 5;
/* the const applies to array elements, i.e. "a[0]" cannot be mutated */
const int arr[] = { 1, 2, 3 };
/* for the lifetime of "ptr", no other pointer could point to the same "int" object */
int *restrict ptr;
/* "s1" can be mutated, but "*s1" cannot */
const char *s1 = "Hello";
/* neither "s2" (because of top-level const) nor "*s2" can be mutated */
const char *const s2 = "World";
/* "*p" may change its value as a result of external conditions, "**p" and "p" cannot */
char *volatile *p;
/* "q", "*q" and "**q" may change their values as a result of external conditions */
volatile char *volatile *volatile q;