Un pointeur vers void
est un type de pointeur "générique". A void *
peut être converti en n'importe quel autre type de pointeur sans un cast explicite. Vous ne pouvez pas déréférencer un void *
ou faire de l'arithmétique de pointeur avec lui ; vous devez d'abord le convertir en un pointeur vers un type de données complet.
void *
est souvent utilisé dans les cas où vous devez pouvoir travailler avec différents types de pointeurs dans le même code. Un exemple fréquemment cité est la fonction de bibliothèque qsort
:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
base
est l'adresse d'un tableau, nmemb
est le nombre d'éléments du tableau, size
est la taille de chaque élément, et compar
est un pointeur vers une fonction qui compare deux éléments du tableau. Elle est appelée comme suit :
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);
Les expressions du tableau iArr
, dArr
y lArr
sont implicitement convertis de types tableau en types pointeur dans l'appel de la fonction, et chacun est implicitement converti de "pointeur à int
/ double
/ long
"en "pointeur vers void
".
Les fonctions de comparaison ressembleraient à quelque chose comme :
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;
}
En acceptant void *
, qsort
peut travailler avec des tableaux de n'importe quel type.
L'inconvénient d'utiliser void *
c'est que vous jetez la sécurité de type par la fenêtre et dans la circulation en sens inverse. Il n'y a rien pour vous protéger de l'utilisation d'une mauvaise routine de comparaison :
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareInt
s'attend à ce que ses arguments pointent vers int
mais travaille en fait avec double
s. Il n'y a aucun moyen de détecter ce problème au moment de la compilation ; vous vous retrouverez simplement avec un tableau mal trié.