Doit déclarer le prototype de fonction en C? [dupliquer]

Cette question a déjà une réponse ici:

Je suis un peu nouveau en C (j'ai déjà Java, C# et une certaine expérience en C++). En C, est-il nécessaire de déclarer un prototype de fonction ou le code peut-il compiler sans lui? Est-ce une bonne pratique de programmation le faire? Ou est-il juste dépend du compilateur? (Je cours Ubuntu 9.10 et utilise le compilateur GNU C, ou gcc, sous L'IDE Code:: Blocks)

50
demandé sur Mohit Deshpande 2010-04-04 20:59:34

10 réponses

Dans ANSI C (ce qui signifie C89 ou C90), vous n'avez pas besoin de déclarer un prototype de fonction; cependant, c'est une bonne pratique de les utiliser. La seule raison pour laquelle la norme vous permet de ne pas les utiliser est la rétrocompatibilité avec un code très ancien.

Si vous n'avez pas de prototype et que vous appelez une fonction, le compilateur déduira un prototype des paramètres que vous transmettez à la fonction. Si vous déclarez la fonction plus tard dans la même unité de compilation, vous obtiendrez une erreur de compilation si la fonction de la signature est différente de ce que le compilateur a deviné.

Pire, si la fonction est dans une autre unité de compilation, il n'y a aucun moyen d'obtenir une erreur de compilation, car sans un prototype, il n'y a aucun moyen de vérifier. Dans ce cas, si le compilateur se trompe, vous pouvez obtenir un comportement indéfini si l'appel de fonction pousse différents types sur la pile que la fonction attend.

Convention est de toujours déclarer un prototype dans un fichier d'en-tête qui a le même nom que le fichier source contenant la fonction.

Dans C99 ou C11, la norme C nécessite une déclaration de fonction dans la portée avant d'appeler une fonction. De nombreux compilateurs n'appliquent pas cette restriction dans la pratique sauf si vous les forcez à le faire.

55
répondu user308405 2015-02-27 05:52:15

Il n'est jamais nécessaire de déclarer un prototype pour une fonction en C, ni dans l'ancien C (y compris C89/90) ni dans le nouveau C (C99). Cependant, il existe une différence significative entre C89 / 90 et C99 en ce qui concerne les déclarations de fonction.

Dans C89 / 90, il n'était pas nécessaire de déclarer une fonction du tout. Si la fonction n'est pas déclarée au point de l'appel, le compilateur "devine" (déduit) la déclaration implicitement à partir des types d'arguments passés dans l'appel et suppose que le type de retour est int.

Par exemple

int main() {
  int i = foo(5); 
  /* No declaration for `foo`, no prototype for `foo`.
     Will work in C89/90. Assumes `int foo(int)` */

  return 0;
}

int foo(int i) {
  return i;
}

En C99 chaque fonction que vous appelez doit être déclaré avant le point de l'appel. Cependant, il n'est pas encore nécessaire de le déclarer avec un prototype spécifiquement. Une déclaration non-prototype fonctionnera également. Cela signifie qu'en C99, la règle" implicit int " ne fonctionne plus (pour les types de retour de fonction inférés, dans ce cas), mais les types de paramètres peuvent toujours être devinés à partir des types d'arguments si la fonction est déclaré sans prototype.

L'exemple précédent ne sera pas compiler en C99, depuis foo n'est pas déclaré au moment de l'appel. Pourtant, vous pouvez ajouter une déclaration non-prototype

int foo(); /* Declares `foo`, but still no prototype */

int main() {
  int i = foo(5); 
  /* No prototype for `foo`, although return type is known. 
     Will work in C99. Assumes `int foo(int)` */

  return 0;
}
...

Et se retrouver avec un code C99 valide.

Néanmoins, c'est toujours une bonne pratique de déclarer un prototype pour la fonction avant de l'appeler.

Une note supplémentaire: j'ai dit plus haut qu'il n'est jamais nécessaire de déclarer un prototype de fonction. En fait, pour certaines fonctions, il est exigence. Afin de bien appeler un variadic fonction en C (printf par exemple), la fonction doit être déclarée , avec un prototype avant le point de l'appel. Sinon, le comportement est indéfini. Ceci s'applique à la fois à C89 / 90 et C99.

60
répondu AnT 2015-02-27 05:53:08

Ce n'est pas un must, si la fonction est définie avant son utilisation.

5
répondu Drakosha 2010-04-04 17:07:44

Ce n'est pas nécessaire, mais c'est une mauvaise pratique de ne pas utiliser de prototypes.

Avec les prototypes, le compilateur peut vérifier que vous appelez la fonction correctement (en utilisant le bon nombre et le bon type de paramètres).

Sans prototypes, il est possible d'avoir ceci:

// file1.c
void doit(double d)
{
    ....
}

int sum(int a, int b, int c)
{
    return a + b + c;
}

Et ceci:

// file2.c

// In C, this is just a declaration and not a prototype
void doit();
int sum();

int main(int argc, char *argv[])
{
    char idea[] = "use prototypes!";

    // without the prototype, the compiler will pass a char *
    // to a function that expects a double
    doit(idea);

    // and here without a prototype the compiler allows you to
    // call a function that is expecting three argument with just
    // one argument (in the calling function, args b and c will be
    // random junk)
    return sum(argc);
}
2
répondu R Samuel Klatchko 2010-04-04 17:13:12

En C, si nous ne déclarons pas un prototype de fonction et utilisons la définition de la fonction, il n'y a pas de problème et le programme compile et génère la sortie si le type de retour de la fonction est "entier". Dans toutes les autres conditions, l'erreur du compilateur apparaît. La raison en est que si nous appelons une fonction et ne déclarons pas de prototype de fonction, le compilateur génère un prototype qui renvoie un entier et recherche la définition de fonction similaire. si le prototype de fonction correspond alors il compile correctement. Si le type de retour n'est pas entier, les prototypes de fonctions ne correspondent pas et génèrent une erreur. Il est donc préférable de déclarer le prototype de fonction dans les fichiers d'en-tête.

2
répondu Raviteja 2014-01-09 16:43:55

C permet d'appeler des fonctions même si elles n'ont pas déjà été déclarées, mais je vous recommande fortement de déclarer un prototype pour toutes les fonctions avant de les utiliser afin que le compilateur puisse vous sauver si vous utilisez les mauvais arguments.

1
répondu Anders Abel 2010-04-04 17:07:55

Vous devez placer les déclarations de fonction dans le fichier d'en-tête (X. h) et la définition dans le fichier source (X. c). Puis d'autres fichiers peuvent #include "X.h" et appeler la fonction.

1
répondu cpalmer 2010-04-04 17:08:09

Le prototype de fonction

N'est pas obligatoire selon la norme C99.

1
répondu zoli2k 2010-04-04 17:13:50

Il n'est pas absolument nécessaire de déclarer une fonction pour que le code appelant soit compilé. Il y a des mises en garde cependant. La fonction non déclarée est supposée renvoyer int et le compilateur émettra d'abord des avertissements sur la fonction non déclarée, puis sur les discordances dans les types de type de retour et de paramètre.

Cela dit, il est évident que déclarer correctement les fonctions avec des prototypes est une bien meilleure pratique.

0
répondu Nikolai Fetissov 2010-04-04 17:10:12

Sélectionnez le menu 'Options', puis sélectionnez ' Compiler / c++ Option’. Dans la boîte de dialogue qui apparaît, sélectionnez "RPC toujours" dans les options’ Utiliser le compilateur C++'. Sélectionnez à nouveau le menu ‘Options’, puis sélectionnez ‘Environnement | Éditeur’. Assurez - vous que l'extension par défaut est ‘C’ plutôt que ‘RPC’.

-3
répondu user3725015 2014-06-10 07:27:08