Pointeurs de fonction en C : Exemples pratiques et bonnes pratiques
Les pointeurs de fonction débloquent de puissantes capacités en C, permettant aux fonctions de manipuler des données directement via des adresses mémoire plutôt que de copier des valeurs. En passant des adresses aux paramètres pointeur, une fonction peut modifier les variables originales, permettant des motifs tels que l'échange sur place, les rappels dynamiques et les fonctions d'ordre supérieur.
- Exemple de pointeurs de fonction
- Fonctions avec paramètres tableau
- Fonctions qui retournent un tableau
- Pointeurs de fonction
- Tableau de pointeurs de fonction
- Fonctions utilisant des pointeurs void
- Pointeurs de fonction comme arguments
Exemple de pointeurs de fonction
La routine d'échange classique démontre comment une fonction peut échanger les valeurs de deux variables en opérant sur leurs adresses.
void swap (int *a, int *b);
int main() {
int m = 25;
int n = 100;
printf("m is %d, n is %d\n", m, n);
swap(&m, &n);
printf("m is %d, n is %d\n", m, n);
return 0;
}
void swap (int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
Sortie :
m is 25, n is 100 m is 100, n is 25
- Déclarer
swapavec deux pointeurs d'entiers. - Initialiser
metndansmainet les afficher. - Appeler
swap(&m, &n)pour passer les adresses. - À l'intérieur de
swap, utiliser une variable temporaire pour échanger les valeurs. - Déréférencer les pointeurs pour lire/écrire les données réelles.
Fonctions avec paramètres tableau
Les tableaux se dégradent en pointeurs quand ils sont passés aux fonctions. Le programme suivant somme les éléments d'un tableau en itérant sur le pointeur.
int add_array (int *a, int num_elements);
int main() {
int Tab[5] = {100, 220, 37, 16, 98};
printf("Total summation is %d\n", add_array(Tab, 5));
return 0;
}
int add_array (int *p, int size) {
int total = 0;
for (int k = 0; k < size; k++) {
total += p[k]; /* équivalent à total += *p; p++; */
}
return total;
}
Sortie :
Total summation is 471
- Définir
add_arraypour accepter un pointeur et une taille, retournant la somme. - Passer le nom du tableau
Tab(qui se dégrade en pointeur) et sa longueur à la fonction.
Fonctions qui retournent un tableau
Une fonction peut retourner un pointeur vers un tableau statique. Cette approche est utile quand l'appelant a besoin d'un tableau temporaire sans gérer l'allocation mémoire.
#include <stdio.h>
int * build_array();
int main() {
int *a;
a = build_array(); /* obtenir les 5 premiers nombres pairs */
for (int k = 0; k < 5; k++)
printf("%d\n", a[k]);
return 0;
}
int * build_array() {
static int Tab[5] = {1,2,3,4,5};
return Tab;
}
Sortie :
1 2 3 4 5
- Déclarer une fonction qui retourne un pointeur vers un tableau statique.
- Utiliser le pointeur retourné pour itérer et afficher le contenu du tableau.
Pointeurs de fonction
Un pointeur de fonction contient l'adresse du point d'entrée d'une fonction, permettant la distribution dynamique et les rappels. La syntaxe de déclaration nécessite des parenthèses autour de l'astérisque pour éviter une mauvaise interprétation.
type_retour (*nom_fonction)(arguments)
Exemple : Appeler une routine via un pointeur.
#include <stdio.h>
void Hi_function (int times); /* fonction */
int main() {
void (*function_ptr)(int); /* pointeur de fonction */
function_ptr = Hi_function; /* assignation */
function_ptr(3); /* invocation */
return 0;
}
void Hi_function (int times) {
for (int k = 0; k < times; k++)
printf("Hi\n");
}
Sortie :
Hi Hi Hi
- Définir une fonction régulière.
- Déclarer un pointeur de fonction avec la signature correcte.
- Assigner le pointeur au nom de la fonction.
- Invoquer la fonction via le pointeur.
Tableau de pointeurs de fonction
Stocker plusieurs pointeurs de fonction dans un tableau permet une approche pilotée par table, similaire à une instruction switch. Le programme suivant démontre une calculatrice simple.
#include <stdio.h>
int sum(int num1, int num2);
int sub(int num1, int num2);
int mult(int num1, int num2);
int divi(int num1, int num2);
int main() {
int x, y, choice, result;
int (*ope[4])(int, int);
ope[0] = sum;
ope[1] = sub;
ope[2] = mult;
ope[3] = divi;
printf("Enter two integer numbers: ");
scanf("%d%d", &x, &y);
printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: ");
scanf("%d", &choice);
result = ope[choice](x, y);
printf("%d", result);
return 0;
}
int sum(int x, int y) {return x + y;}
int sub(int x, int y) {return x - y;}
int mult(int x, int y) {return x * y;}
int divi(int x, int y) {return y != 0 ? x / y : 0;}
Résultat : Entrer 13 48 2 → 624
- Définir quatre fonctions arithmétiques.
- Créer un tableau de quatre pointeurs de fonction avec signatures correspondantes.
- Assigner chaque pointeur à la fonction correspondante.
- Récupérer le choix de l'utilisateur et appeler la fonction sélectionnée.
Fonctions utilisant des pointeurs void
Les pointeurs void fournissent un accès agnostique au type aux données. Utilisés dans les paramètres de fonction, ils permettent à la routine d'accepter n'importe quel type de données, à condition que l'appelant fournisse le cast correct.
void * cube (const void *);
Programme d'exemple :
#include <stdio.h>
void* cube (const void* num);
int main() {
int x = 4;
int cube_int = (int)cube(&x);
printf("%d cubed is %d\n", x, cube_int);
return 0;
}
void* cube (const void *num) {
int result = (*(int *)num) * (*(int *)num) * (*(int *)num);
return (void*)result;
}
Résultat : 4 cubed is 64
- Définir une fonction qui accepte un pointeur void const et retourne un pointeur void.
- Caster le pointeur vers
int *pour accéder à la valeur. - Calculer le cube et caster le résultat vers
void *pour le retour.
Pointeurs de fonction comme arguments
Passer un pointeur de fonction à une autre fonction est un motif courant pour les rappels. La bibliothèque standard qsort utilise cette technique pour trier des tableaux de types arbitraires.
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *));
Exemple qui trie un tableau d'entiers :
#include <stdio.h>
#include <stdlib.h>
int compare (const void *, const void *);
int main() {
int arr[5] = {52, 14, 50, 48, 13};
size_t num = sizeof(arr)/sizeof(arr[0]);
size_t width = sizeof(arr[0]);
qsort((void *)arr, num, width, compare);
for (size_t i = 0; i < num; i++)
printf("%d ", arr[i]);
return 0;
}
int compare (const void *elem1, const void *elem2) {
int a = *(int *)elem1;
int b = *(int *)elem2;
return (a - b);
}
Résultat : 13 14 48 50 52
- Implémenter
comparepour retourner négatif, zéro ou positif basé sur les deux entiers. - Déterminer la taille du tableau et la largeur d'élément avec
sizeof. - Appeler
qsortavec le tableau, le compte, la largeur et la fonction de comparaison. - Afficher le tableau trié pour vérifier l'opération.
Langue C
- Quatre modèles éprouvés pour les fonctions définies par l'utilisateur en C
- Boucle do-while en C++ : Syntaxe, exemples pratiques et boucles imbriquées
- Maîtriser les pointeurs en C++ : Concepts, exemples et applications pratiques
- Surcharge d'opérateurs en C++ : Guide pratique avec exemples de code
- Les Fonctions en C++ Expliquées avec des Exemples de Code Pratiques
- Maîtriser les Collections C# : Tutoriel Pratique avec Exemples Réels
- Pointeurs en C : Guide complet sur les types, utilisation et bonnes pratiques
- Maîtriser str.count() de Python : Compter caractères et sous-chaînes avec exemples
- Maîtriser les fonctions lambda Python : exemples pratiques et bonnes pratiques