Type Qualifiers in C
C has 3 type qualifiers: const, volatile, and restrict.
const
A constant makes a value constant; the variable can't be reassigned or modified. Doing so will be a compilation error.
int main() {
const int i = 10;
i++; // error
}
The above code will not compile, as we are trying to mutate a constant variable.
int main() {
const int i = 10;
int j = 12;
//Pointer to a constant integer (Value cannot change, pointer can)
const int* const_ptr = &j;
//Constant pointer to a regular integer (Pointer cannot change, value can)
int* const const_val_ptr = &j;
//Both the pointer and the value it points to are constant
const int* const const_val_const_ptr = &j;
}
const int* ptr: The pointer can point to any other int, but can't mutate the int; i.e a read-only pointer.int* const ptr: The pointed-to value can be mutated, but it can't point to any other int.const int* const ptr: Neither the value can be mutated, nor can the pointer be updated to point to anything else. Both the pointer and the value are constant.
Function Argument Declarations
const can be used in function argument declaration.
int print(size_t size, const int arr[static size]);
The above function accepts a pointer to an array, but it can only read the values; it can't write to it.
Note: static size tells the compiler the array must have at least size elements and cannot be NULL.
volatile
Tells the compiler not to perform read optimisations on a variable, as some other thread or non-obvious code might change the variable's value. The compiler will not cache the value of the variable between reads, because other code might have changed it.
volatile tells the compiler not to perform read optimisations on a variable, as some other thread or non-obvious code might change the variable's value.
int main() {
volatile int i = 10;
int a = i;
/* some code */
int b = i;
}
The volatile qualifier tells the compiler not to cache the value of i between a and b, because other code might have changed it.
restrict
Used when we want to indicate that the same memory location can't be accessed by more than one pointer. So the compiler can apply some optimisations.
Making a pointer restrict and accessing it with another pointer is undefined behaviour.
int main() {
int i = 10;
int* restrict ptr = &i;
}
Function Argument Declarations
restrict qualifier can be used in argument declarations.
int move(size_t size, int destination[restrict static size], const int src[restrict static size]);
The above function accepts pointers of 2 arrays that are distinct and have no overlap.
Note: static size tells the compiler the array must have at least size elements and cannot be NULL.
