Dans le langage C, les prototypes de fonction sont des déclarations de fonctions qui informent le compilateur sur le type de retour, le nom et les types de paramètres de la fonction avant sa réelle implémentation. Les prototypes sont généralement placés dans des fichiers d'en-tête (.h). Leur utilisation permet :
Exemple de prototype :
// math_utils.h int sum(int a, int b); // Prototype de la fonction
// main.c #include "math_utils.h" int main() { int result = sum(3, 4); // le compilateur connaît la signature de sum }
Sans prototype, la fonction serait interprétée comme retournant int et acceptant un nombre indéfini d'arguments, ce qui peut entraîner des erreurs d'exécution inattendues.
Question : Peut-on appeler une fonction en C avant sa définition, si elle n'est pas déclarée comme prototype ?
Réponse : La norme C89 autorisait l'appel de fonctions avant leur définition si la valeur de retour était un int, et si les paramètres n'étaient pas vérifiés (int implicite, promotion implicite). Dans les normes modernes, cela entraîne des avertissements ou des erreurs, et cette approche ne doit pas être utilisée.
Exemple d'erreur :
int main() { foo(1, 2); // Pas de prototype pour foo } int foo(double x, double y) { ... }
Le compilateur appellerait la fonction en considérant les paramètres comme des int, bien que la signature implique des doubles — résultat : UB ou valeurs incorrectes.
Histoire
Dans un grand projet scientifique, l'un des modules manquait de prototypes pour les fonctions de traitement des données. En passant un
floatau lieu d'unint, les erreurs n'ont été détectées qu'après des calculs incorrects lors de l'exploitation, bien que la compilation se soit déroulée sans erreurs.
Histoire
Dans un utilitaire de build modulaire, les fonctions étaient définies uniquement dans des fichiers
.c, sans déclarations dans les en-têtes. Dans deux modules, des fonctions avec le même nom et des paramètres incompatibles ont été définies — entraînant une erreur difficile à déceler lors du lien.
Histoire
Dans un projet pour système embarqué, un problème est survenu : la fonction d'initialisation était appelée avant sa définition sans prototype. En raison de l'hypothèse du compilateur sur les types de paramètres et de retour, la logique était fortement perturbée et le système se plantait uniquement sur certaines constructions avec une organisation de mémoire différente.