Вказівник на void- це "загальний" тип вказівника. A void *може бути перетворений у будь-який інший тип вказівника без явного виступу. Ви не можете знеструмлювати void *або виконувати арифметику вказівника з ним; ви повинні спочатку перетворити його в покажчик на повний тип даних.
void *часто використовується в місцях, де вам потрібно мати можливість працювати з різними типами вказівників в одному і тому ж коді. Одним із часто цитованих прикладів є функція бібліотеки qsort:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
base- адреса масиву, nmembце кількість елементів у масиві, sizeрозмір кожного елемента і comparє вказівником на функцію, яка порівнює два елементи масиву. Це називається так:
int iArr[10];
double dArr[30];
long lArr[50];
...
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);
Вирази масиву iArr, dArrі lArrнеявно перетвориться з типів масивів для типів покажчиків у виклику функції, і кожен неявно перетворюються з «покажчика int/ double/ long» в «покажчик void».
Функції порівняння виглядали б приблизно так:
int compareInt(const void *lhs, const void *rhs)
{
const int *x = lhs; // convert void * to int * by assignment
const int *y = rhs;
if (*x > *y) return 1;
if (*x == *y) return 0;
return -1;
}
Приймаючи void *, qsortможна працювати з масивами будь-якого типу.
Недоліком використання void *є те, що ви викидаєте безпеку типу у вікно та в зустрічний рух. Нічого не захистить вас від використання неправильної процедури порівняння:
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareIntочікує, що його аргументи будуть вказувати на ints, але насправді працює з doubles. Неможливо знайти цю проблему під час компіляції; ти просто закінчишся з помилковим масивом.