pointeur générique

Les fonctions calloc et malloc d’allocation de mémoire à partit du tas sont deux exemples de fonctions rendant un résultat de type *void, le pointeur sur la zone allouée.

Le type *void sert à disposer de fonctions manipulant des objets pointés (ou des pointeurs) d’un type quelconque.

Quelle différence entre *void et *char?

L’exemple qui suit permet de montrer la différence entre les type *void et l’ancien type générique *char. Il s’agit d’écrire une fonction qui copie une zone mémoire de n octets dans une autre, et rend un pointeur sur la première zone. Il devra être facile et souple d’utiliser cette fonction quelque soit le type des paramètres utilisés.

La définition de fonction ci-dessous est incorrecte, car il est interdit d’accéder à l’objet pointé par un pointeur générique.

void * copie (void * dest , void * depart, int n) {

void * d = depart ;

while (n--)

*dest ++ = *depart++ ; /* Ecrire *dest est interdit */

return d ;

}

Il faut écrire :

char * copie (char * dest , char * depart, int n) {

char * d = depart ;

while (n--)

*dest ++ = *depart++ ; /* Ecrire *dest est interdit */

return d ;

}

Pour bénéficier des conversions implicites, on peut quand on veut utiliser la fonction écrire la déclaration :

void * copie (void * dest , void * depart, int n) ;

Pour la définition de fonction comporte un corps. La déclaration ne comporte que la signature.

La définition et la déclaration d’une fonction peuvent avoir des signatures qui diffèrent par le type des paramètres.

Ce qui permettra d’appeler la fonction pour copier par exemple des tableaux (l’utilisation de *char aurait nécessité des conversions explicites par l’opération cast).

int tab1[50], tab2[50], *pt_tab_int ;

float tab3[80], tab4[80], *pt_tab_float ;

pt_tab_int = copie (tab1, tab2, 50*sizeof(int));

pt_tab_float = copie (tab3, tab4, 80*sizeof(float));

/* ce ne sont pas les tableaux qui sont passés en paramètres effectifs, mais les pointeurs sur le premier octet de chaque tableau */

Utilisation de **void

Le second exemple correspond à la définition d’une fonction générale d’échange de deux pointeurs sans affecter les objets pointés. Il faut utiliser le type **void, et non *void.

La raison est que le passage des paramètres en C se fait par copie, les paramètres effectifs seraient inchangés avec le type *void.

void echange (void ** p , ** q) {

void *inter ;

inter = *p ;

*p = *q ;

*q = inter ;

}

int *int 1 ; int 2 ;

/* pour pouvoir échanger les valeurs des pointeurs int 1 et int2, je passe leur adresse */

echange (&int1, &int2) ;

» Glossaire du langage C