Quel est le but de cette ligne? (Déclaration de fonction)

Je travaille par le biais de K & R pour apprendre la programmation. Ça va bien jusqu’à présent, mais le rôle d’une ligne de code de la section 1.8 (fonctions) n’est pas clair.

Dans la section 1.8, les auteurs vous montrent comment créer une fonction pour élever un entier à la puissance d’un autre entier.

J’ai collé le code ci-dessous, tel qu’il était écrit dans le livre. Tout se passe bien. Mais je ne sais pas pourquoi ils ont inclus cette ligne en haut:

int power(int m, int n); 

Le livre ne le mentionne pas, mis à part le fait que le programme va élever m au pouvoir n. Si je supprime la ligne du code, le programme restitue comme il se doit.

Si je comprends bien, la ligne

 int power(int base, int n) 

crée la fonction et les accolades en dessous définissent la fonction. Ensuite, les accolades situées sous main appellent la fonction pour afficher le graphique.

Donc, tout cela semble avoir du sens. Mais je ne vois pas ce que la très haute ligne fait.

Cela pourrait être superficiel, mais il semble beaucoup plus probable que je manque quelque chose. Quelqu’un peut-il m’expliquer pourquoi cette ligne est là?

 #include  int power(int m, int n); /* test power function */ main() { int i; for (i = 0; i = 0 */ int power(int base, int n) { int i, p; p = 1; for (i = 1; i <= n; ++i) p = p * base; return p; } 

La première ligne est la déclaration de la fonction. Le bloc de code en bas est la définition de la fonction.

À partir de la version 1999 de la norme ISO C, il est illégal (violation de contrainte) d’appeler une fonction sans déclaration visible. la déclaration doit précéder l’appel.

Pour un programme simple comme celui-ci, vous pouvez simplement écrire la définition complète de power() avant la définition de main() (car une définition fournit également une déclaration), mais pour les cas plus complexes (tels que les appels récursifs), vous avez souvent besoin de fournir une déclaration séparée.

Pour les programmes plus volumineux, il est courant de collecter toutes les déclarations de fonction dans un fichier d’en-tête ( foo.h , par exemple), ainsi que les définitions correspondantes dans un fichier source ( foo.c , par exemple). Une directive #include "foo.h" est utilisée pour rendre les déclarations visibles dans d’autres fichiers. Vous verrez ce genre de chose plus tard dans le livre.

(Dans les versions 1990 et antérieures de C, couvertes par K & R2, il est parfois possible d’appeler une fonction sans déclaration visible, mais il est néanmoins très judicieux de fournir des déclarations explicites.)

Incidemment, la déclaration du programme principal devrait être vraiment int main(void) plutôt que simplement main() .

Terminologie: un “prototype” est une déclaration de fonction qui spécifie les types de parameters.

 int power(int base, int n); /* a declaration that's also a prototype */ int power(int, int); /* likewise */ int power(); /* a declaration but not a prototype */ 

(Les noms de paramètre sont obligatoires dans une définition, mais facultatifs dans une déclaration autonome.)

Comme cas particulier, un prototype de fonction sans paramètre utilise (void) , car les parenthèses vides désignent déjà une déclaration non-prototype. Ainsi, int main(void) est un prototype, mais int main() ne l’est pas.

Les déclarations non prototypes sont “obsolètes”, ce qui signifie qu’elles pourraient en théorie être supprimées d’une future norme linguistique. Mais ils sont obsolètes depuis 1989 et même dans la nouvelle norme ISO C de 2011, le comité n’a pas jugé bon de les supprimer.

 int power(int m, int n); 

est une déclaration de la fonction de power sous sa forme prototype. Une déclaration de fonction informe le compilateur du nombre de parameters de la fonction, du type de ses parameters et du type de la valeur de retour de la fonction.

En C, vous ne pouvez pas utiliser un identifiant de fonction avant qu’il ait été déclaré.

C’est une déclaration forward qui rend publique l’ interface de fonction car celle-ci est utilisée avant d’être réellement implémentée sous main() .

Les fichiers d’en-tête, que vous #include fournissent une fonctionnalité similaire permettant de rendre l’API appelable publique — mais le code est ensuite généralement fourni dans une bibliothèque plutôt que via la même unité de compilation que dans cet exemple à fichier unique de K & R Chapitre d’intro.

Si vous n’incluez pas cette ligne en haut, lorsque le programme atteint le power(2,i) alimentation principale n’a pas encore été déclarée. Les programmes sont lus de haut en bas, et en plaçant la déclaration en haut, le compilateur sait qu’une définition est à venir.

Cette ligne est juste le prototype de fonction. C’est une déclaration forward qui permet au code de pouvoir utiliser une fonction avec cette signature qui existera lorsque tout sera lié. Sans lui, la fonction main() tentera d’utiliser la fonction power() mais le compilateur n’est pas encore au courant, car elle n’est pas définie plus tard dans le fichier source.

La ligne en haut à laquelle vous faites référence est un prototype de fonction. La SEULE chose pour laquelle il existe est que le compilateur puisse vérifier votre travail, c’est-à-dire, pour vous assurer que vous utilisez la fonction correctement en transmettant les types et le nombre d’arguments appropriés. C’est tout ce que c’est. C’est pourquoi vous pouvez le supprimer et le code est toujours compilé – vous ne le supprimez que par la suppression de la référence du compilateur afin qu’il ne puisse pas vérifier votre travail. Et si vous le supprimez, il est possible que vous passiez le type d’argument incorrect et causiez une erreur d’exécution ou un blocage de programme difficile à trouver. Mais le laisser entrer permet au compilateur de signaler une telle erreur au moment de la compilation, ce qui vous évite des ennuis. Et sauver du chagrin est une bonne chose.

Plus tard, avec la norme C99, ils ont décidé de rendre obligatoire la fourniture d’un prototype de fonction (ou bien de définir d’abord la fonction) afin que le code puisse être compilé, ce qui vous obligeait à laisser le compilateur vérifier votre travail.