Указатель на void
Указатель типа void * не имеет базового типа и для дальнейшей работы с ним к нему надо применить операцию явного преобразования типа.
Указатель типа void * указывает на все, что угодно. Ключевому слову void здесь приписывается не значение “ничего”, а противоположное значение ”все, что угодно”. Под слово void подпадают базовые типы, пользовательские типы, любые указатели: одинарные, двойные и т.д.
Таким образом, объявление void **ptr не имеет смысла, хотя и не будет являться логической ошибкой. Надо писать void *ptr.
В операциях присваивания указатель на void может стоять в левой части. Это означает, что указателю void* можно присвоить любой указатель. При размещении указателя void* в правой части его надо преобразовывать к указательному типу левой части. Например.
int i=5, *pi = &i;
void *ptr;
ptr = pi;
//pi = ptr; ошибка
pi = (int *)ptr; // правильно
Константные указатели
При объявлении указателей можно использовать зарезервированное слово const. В отличие от обычных констант и макроподстановок константные объекты размещаются в памяти, но не являются объектами Lvalue, то есть не могут стоять в левой части операции присваивания.
Пример 1.
int *Arr = {1,3,2,4,5}, *B = {1,1};
При данном определении допустимы следующие два оператора
Arr[0]=100;
Arr = B;
Пример 2.
const int *Arr = {1,3,2,4,5}, *B = {1,1};
// Arr[0]=100; ошибка
Arr = B;
Пример 3.
int *const Arr = {1,3,2,4,5}, *B = {1,1};
Arr[0]=100;
//Arr = B; ошибка
Пример 4.
const int *const Arr = {1,3,2,4,5}, *B = {1,1};
//Arr[0]=100; ошибка
//Arr = B; ошибка
Обычно константные указатели используют для строк
const char* str = “Hello”;
В этом случае защищается содержимое текстовых строк.