Déclaration des fonctions C dans K & R

Je ne suis pas familier avec la déclaration de fonction de style K & R.

Après comstack, avec avertissement (juste lié au retour de la valeur de main qui aussi avec -Wall ) mais quels sont les types de données des variables utilisées?

 main(a, b, c, d){ printf("%d", d); } foo(a, b){ a = 2; b = 'z'; } 

Si cela est demandé avant, veuillez indiquer le lien dans la section commentaire. Je ne pouvais pas trouver quelque chose de similaire.

modifier

Je viens de tomber sur un code C obscurci, qui les utilise.
Mais je peux vous assurer que je n’utiliserai pas cette syntaxe dans la programmation en langage C.

“K & R C” fait référence au langage défini par la première édition de 1978 du livre de Kernighan & Ritchie “The C Programming Language”.

Dans K & R (c’est-à-dire, avant l’ANSI) C, les entités pourraient généralement être déclarées sans un type explicite et utiliseraient par défaut le type int . Cela remonte aux langues ancêtres de C, B et BCPL.

 main(a,b,c,d){ printf("%d", d); } 

C’est presque équivalent à:

 int main(int a, int b, int c, int d) { printf("%d", d); } 

L’ancienne syntaxe est restée légale mais obsolète dans ANSI C (1989) et ISO C (1990), mais la norme ISO C de 1999 a abandonné la règle “implicite int” (tout en conservant la syntaxe de déclaration et de définition à l’ancienne).

Notez que j’ai dit que c’est presque équivalent. C’est essentiellement la même chose quand on le considère comme une définition, mais comme une déclaration, il ne fournit pas d’informations de type de paramètre. Avec l’ancienne définition, il n’est pas nécessaire de diagnostiquer un appel avec un nombre ou des types d’arguments incorrects; c’est juste un comportement indéfini. Avec un prototype visible, les arguments incompatibles déclenchent un diagnostic au moment de la compilation – et, lorsque cela est possible, les arguments sont convertis implicitement en type de paramètre.

Et puisqu’il s’agit d’une définition du terme main , il existe un autre problème. La norme ne spécifie que deux formes pour main (une sans arguments et une avec deux arguments, argc et argv ). Une implémentation peut prendre en charge d’autres formes, mais un avec quatre arguments int ne sera probablement pas l’un d’entre eux. Le comportement du programme n’est donc pas défini. En pratique, il est probable que d aura une valeur résiduelle lors de l’appel initial. (Et oui, un appel récursif à main est autorisé en C, mais rarement une bonne idée.)

 foo(a,b){ a = 2; b = 'z'; } 

C’est presque équivalent à:

 int foo(int a, int b) { a = 2; b = 'z'; } 

(Et notez que 'z' est de type int , pas de type char .)

Et encore une fois, l’ancien formulaire ne vous donne pas la vérification du type de paramètre, donc un appel comme:

 foo("wrong type and number of arguments", 1.5, &foo); 

n’a pas besoin d’être diagnostiqué.

En bout de ligne: il est bon de savoir comment fonctionnent les déclarations de fonction et les définitions de style K & R. Il y a encore du vieux code qui les utilise, et ils sont toujours légaux (mais obsolètes) même en C2011 (bien que sans la règle “implicitement int”). Mais il n’ya pratiquement aucune bonne raison d’écrire du code qui les utilise (sauf si vous êtes coincé avec un très vieux compilateur, mais c’est rare et de plus en plus rare.)

Mais je peux vous assurer que je n’utiliserai pas cette syntaxe dans la programmation en langage C.

Excellent!

Dans la définition de fonction de style K & R, le type du paramètre est spécifié par un ensemble dédié de déclarations placé entre la fonction “signature” et le corps de la fonction. Par exemple, cette définition de fonction

 void foo(a, b, c) double a; char b; { ... } 

utilise des parameters de type double , char et int . C’est en fait là et comment entre en jeu la règle “int implicite”: puisque le paramètre c n’a pas été mentionné dans la liste de déclarations ci-dessus, il est supposé avoir le type int .

Notez le détail important, qui, à mon avis, n’est pas suffisamment clarifié par d’autres réponses: le paramètre c a le type int non pas parce que le type est manquant dans la liste des parameters de la fonction, mais plutôt parce qu’il n’est pas mentionné dans la séquence des déclarateurs qui suit la fonction ” signature “(avant le corps de la fonction). Dans les déclarations de style K & R, les types sont toujours absents de la liste des parameters de fonction (c’est la caractéristique qui définit la déclaration K & R), mais cela ne signifie pas pour autant que tous les parameters sont supposés être de type int .

PS Notez que C99 prend toujours en charge les déclarations de style K & R, mais depuis que C99 a interdit la règle “int implicite”, il vous oblige à mentionner tous les parameters de fonction dans cette liste de déclaration après la fonction “signature”. L’exemple ci-dessus ne sera pas compilé en C99 pour cette raison. int c doit être ajouté à la liste de déclaration.

Le paramètre par défaut est de type int en C et à propos de la syntaxe K & R, veuillez consulter ici et ici .

Dans C89, le type de variable par défaut est int : il est défini comme implicite int . Cette règle a été révoquée dans C99.

Dans votre exemple, il est compilé comme suit:

 main(int a,int b,int c,int d){printf("%d", d);} foo(int a,int b){a=2; b='z';}