La question que vous vous poser deux questions, pas un seul. La plupart des réponses à ce jour tenté de couvrir la totalité de la chose avec un générique de couverture "c'est K&R style" réponse, alors qu'en fait, seulement une petite partie de cela n'a rien à voir avec ce qui est connu comme le K&R de style (sauf si vous voyez l'ensemble du langage C "K&R-style" d'une manière ou d'une autre :)
La première partie est l'étrange syntaxe utilisée dans la fonction de définition de
int func(p, p2)
void *p;
int p2; /* <- optional in C89/90, but not in C99 */
{
return 0;
}
Celui-ci est en fait un K&R-style de définition de la fonction. D'autres réponses ont couvert ce assez bien. Et il n'y a pas grand-chose, en fait. La syntaxe est obsolète, mais toujours intégralement pris en charge, même en C99 (sauf pour les "non implicite int" la règle en C99, ce qui signifie qu'en C99 vous ne pouvez pas omettre la déclaration d' p2
).
La deuxième partie a peu à voir avec le K&R-style. Je me réfère au fait que la fonction peut être appelée avec "échangé" des arguments, c'est à dire pas de paramètre de type de vérification prend place dans un tel appel. Cela a très peu à voir avec le K&R-définition de style en soi, mais il a tout à voir avec votre fonction ayant pas de prototype. Vous voyez, C lorsque vous déclarez une fonction comme ceci
int foo();
il fait déclare une fonction foo
qui prend un nombre quelconque de paramètres de type inconnu. Vous pouvez l'appeler comme
foo(2, 3);
et comme
j = foo(p, -3, "hello world");
sna ainsi de suite (vous voyez l'idée);
Seul l'appel avec les arguments appropriés va "travailler" (ce qui signifie que les autres produisent un comportement indéfini), mais il est entièrement à vous pour s'assurer de son exactitude. Le compilateur n'est pas nécessaire pour diagnostiquer le mauvais, même si celles-il en quelque sorte comme par magie sait le bon paramètre de types et de leur nombre total.
En fait, ce comportement est une fonction de C langue. Un dangereux, mais une caractéristique néanmoins. Il permet de faire quelque chose comme ceci
void foo(int i);
void bar(char *a, double b);
void baz(void);
int main()
{
void (*fn[])() = { foo, bar, baz };
fn[0](5);
fn[1]("abc", 1.0);
fn[2]();
}
c'est à dire mélanger différents types de fonction dans un "polymorphe" tableau sans typecasts (variadic des types de fonction ne peut pas être utilisé ici). Encore une fois, dangers inhérents à cette technique sont tout à fait évident (je ne me souviens jamais de l'utiliser, mais je peux imaginer ce que ça peut être utile), mais que du C, après tout.
Enfin, le peu qui relie la deuxième partie de la réponse à la première. Lorsque vous effectuez un K&R-style de définition de la fonction, il n'est pas de présenter un prototype de la fonction. Aussi loin que le type de fonction est concerné, votre func
définition déclare func
comme
int func();
c'est à dire ni les types pas le nombre total de paramètres est déclarée. Dans votre message vous dites "... il semble à spécifier est le nombre de paramètres qu'il utilise ...". Formellement parlant, il n'est pas! Après vos deux paramètres K&R-style func
définition, vous pouvez toujours appeler func
comme
func(1, 2, 3, 4, "Hi!");
et il n'y aura pas de violation de contrainte en elle. (Normalement, une qualité compilateur va vous donner un avertissement).
Aussi, parfois négligé le fait est que
int f()
{
return 0;
}
est également un K&R-style de définition de la fonction qui ne présentent pas un prototype. Pour faire "moderne" que vous auriez à mettre explicite void
dans la liste des paramètres
int f(void)
{
return 0;
}
Enfin, contrairement à une croyance populaire, les deux K&R-style des définitions de fonction et non un prototype de fonction déclarations sont entièrement pris en charge en C99. L'ancien a été abandonné depuis C89/90, si je me souviens bien. C99 exige la fonction doit être déclarée avant la première utilisation, mais la déclaration n'est pas nécessaire d'être un prototype. La confusion apparemment découle de la populaire terminologiques mix-up: beaucoup de gens appellent de toute déclaration de la fonction "prototype", alors qu'en fait, la fonction de "déclaration" n'est pas la même chose que le "prototype".