ProgrammationDéveloppeur système

Décrivez les caractéristiques de la déclaration et de l'utilisation des pointeurs sur fonctions en C. Comment stocker correctement un tableau de pointeurs sur différentes fonctions et les appeler dynamiquement ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Un pointeur sur fonction en C est une variable qui stocke l'adresse d'une fonction, permettant de choisir dynamiquement quelle fonction appeler. La déclaration habituelle d'un pointeur sur fonction est :

// Pointeur sur fonction prenant un int et retournant un int int (*f_ptr)(int);

Pour un tableau de pointeurs :

int func1(int x) { return x + 1; } int func2(int x) { return x * 2; } int (*f_arr[2])(int) = { func1, func2 }; int result = f_arr[1](10); // retournera 20
  • Cette approche permet de créer des tableaux de commandes, des gestionnaires ou de lier automatiquement des actions à un numéro d'opération.
  • Toutes les fonctions doivent avoir la même signature.
  • Lors de l'utilisation de pointeurs sur fonctions, les types doivent correspondre exactement.

Question piège

Peut-on appeler une fonction avec une autre signature à l'aide d'un pointeur sur fonction ?

Réponse incorrecte fréquente : « Oui, si l'on utilise un cast. »

Réponse correcte : Techniquement, c'est possible en raison de la nature dynamique des pointeurs, mais cela conduit à des bogues à l'exécution et à un comportement imprévisible, car des fonctions avec des conventions d'appel et des agencements d'arguments différents sont appelées.

Exemple :

void funcA(int x) { printf("A: %d ", x); } void funcB(float y) { printf("B: %f ", y); } void (*fptr)(int) = (void (*)(int)) funcB; fptr(5); // ERREUR : des données incorrectes seront transmises

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet


Histoire

Dans un projet de système de plugins, des fonctions avec des signatures différentes ont été placées dans le tableau de pointeurs (l'une retournant un int, l'autre void). Lors de l'exécution sur certaines architectures, cela a entraîné la corruption de la pile.

Histoire

Dans un ancien système de gestion des commandes, un tableau de pointeurs sur fonctions était utilisé. Un nouveau venu a ajouté une fonction avec des paramètres supplémentaires, ce qui a entraîné un comportement imprévisible après le passage au nouvel élément du tableau.

Histoire

Dans le firmware, le résultat du changement de pointeurs sur fonctions n'était pas vérifié. Une initialisation insuffisante du tableau des gestionnaires a conduit à l'appel d'un pointeur nul (NULL), après quoi l'appareil bloquait sans avertir l'utilisateur.