Um ponteiro para voidé um tipo de ponteiro "genérico". A void *pode ser convertido para qualquer outro tipo de ponteiro sem uma conversão explícita. Você não pode desreferenciar um void *ponteiro ou fazer aritmética com ele; você deve convertê-lo em um ponteiro para um tipo de dados completo primeiro.
void *é frequentemente usado em locais onde você precisa trabalhar com diferentes tipos de ponteiros no mesmo código. Um exemplo comumente citado é a função de biblioteca qsort:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
baseé o endereço de uma matriz, nmembé o número de elementos na matriz, sizeé o tamanho de cada elemento e comparé um ponteiro para uma função que compara dois elementos da matriz. É assim chamado:
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);
As expressões de matriz iArr, dArre lArrsão convertidos implicitamente a partir de tipos de matriz para tipos de ponteiro na chamada de função, e cada um é implicitamente convertido de "ponteiro a int/ double/ long" a "ponteiro de void".
As funções de comparação seriam parecidas com:
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;
}
Ao aceitar void *, qsortpode trabalhar com matrizes de qualquer tipo.
A desvantagem do uso void *é que você joga a segurança de tipos pela janela e entra no tráfego que se aproxima. Não há nada para protegê-lo de usar a rotina de comparação errada:
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareIntespera que seus argumentos apontem para ints, mas na verdade está trabalhando com doubles. Não há como detectar esse problema no momento da compilação; você acabará com uma matriz distorcida.