Regardez la fonction swap suivante, qui échange le contenu de deux éléments, en utilisant l'entier int comme exemple :
void swap(int* i1,int* i2){
int temp;
temp = *i1;
*i1 = *i2;
*i2 = temp;
}
Lorsque vous souhaitez échanger deux types char, vous devez encore réécrire une fonction avec un paramètre de type char. Pouvons-nous utiliser un pointeur void comme paramètre ? Voir les modifications suivantes :
void swap(void *vp1,void *vp2){
void temp = *vp1;
*vp1 = *vp2;
*vp2 = temp;
}
Ce code est incorrect et ne compilera pas. Premièrement, les variables ne peuvent pas être déclarées commevoidvoid. Et vous ne savez pas quel est le type du paramètre passé à cette fonction, vous ne pouvez donc pas déterminer une déclaration de type. En même temps, vous ne pouvez pas appliquer*l'appliquer à un pointeur void, car le système n'a aucune information sur la taille de l'objet pointé par cette adresse. Au moment de la compilation, le compilateur ne peut pas connaître le type du paramètre passé à cette fonction. Pour implémenter ici une fonction générique, vous devez transmettre la taille de l'espace d'adressage size des objets à échanger sur le site d'appel, et utiliser la fonction memcpy() définie dans le fichier d'en-tête string.h. Les modifications sont les suivantes :
void swap(void *vp1,void *vp2,int size){
char buffer[size];//注意此处gcc编译器是允许这样声明的
memcpy(buffer,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buffer,size);
}
Lors de l'appel de cette fonction, vous pouvez l'appeler comme suit (cela s'applique également à d'autres types de x, y) :
int x = 27,y = 2; swap(&x,&y,sizeof(int));
Ensuite, examinons une fonction avec une autre fonctionnalité :
int lsearch(int key,int array[],int size){
for(int i = 0;i < size; ++i)
if(array[i] == key)
return i;
return -1;
}
Cette fonction recherche l'élément key dans le tableau array. S'il est trouvé, elle renvoie son index ; sinon, elle renvoie -1.
Comme ci-dessus, les fonctions génériques peuvent également être implémentées :
void* lsearch(void* key, void *base, int n, int elemSize){
for(int i = 0;i < n; ++i){
void *elemAddr = (char *)base+i*elemSize;
if(memcmp(key, elemAddr, elemSize) == 0)
return elemAddr;
}
return NULL;
}
Ligne 3 du code : le transtypage de la première adresse du tableau en un pointeur de type char utilise la caractéristique selon laquelle le type char a une taille de 1 octet, de sorte que elemAddr pointe vers la première adresse du (i-1)ᵉ élément de ce tableau « générique ». Comme mentionné précédemment, à ce stade, vous ne savez pas quel type de données vous avez transmis, et le système ne peut pas déterminer la longueur d'un élément de ce tableau ni combien d'octets sont nécessaires pour passer à l'élément suivant. Par conséquent, en transtypant vers un pointeur vers char et en ajoutant le produit de l'information de taille d'élément transmise et du compteur cumulé i, c'est-à-dire l'adresse de décalage, vous pouvez obtenir la première adresse du (i-1)ᵉ élément de ce tableau. Ainsi, quel que soit le type de pointeur vers lequel pointe le paramètre transmis, vous pouvez obtenir un pointeur vers l'élément correct, mettant ainsi en œuvre la programmation générique.
Prototype de la fonction memcmp() : int memcmp(void *dest, const void *src, int n), compare le contenu de deux zones mémoire de longueur n dont les premières adresses sont respectivement dest et src.
Cette fonction recherche l'élément clé dans le tableau base. Si elle le trouve, elle renvoie ses informations d'adresse ; sinon, elle renvoie NULL.
Si des pointeurs de fonction sont utilisés, la généricité de son comportement peut être obtenue :
void *lsearch(void *key,void *base,int n,int elemSize,int(*cmpfn)(void*,void*,int)){
for(int i = 0;i < n; ++i){
void *elemAddr = (char *)base+i*elemSize;
if(cmpfn(key,elemAddr,elemSize) == 0)
return elemAddr;
}
return NULL;
}
Définissez ensuite une fonction à appeler :
int intCmp(void* elem1,void* elem2){
int* ip1 = elem1;
int* ip2 = elem2;
return *ip1-*ip2;
}
Regardez l'appel suivant :
int array[] = {1,2,3,4,5,6};
int size = 6;
int number = 3;
int *found = lsearch(&number,array,size,sizeof(int),intCmp);
if(found == NULL)
printf("NO\n");
else
printf("YES\n");
Le C peut également mettre en œuvre un certain degré de programmation générique, mais ce n'est pas sûr et le système n'effectue que des vérifications limitées à ce sujet. Vous devez être extrêmement prudent lors de la programmation.
URL d'origine : https://www.cnblogs.com/wuyudong/p/c-general-function1.html