S’il vous plaît jeter un oeil à mes codes ci-dessous
#include void printOut() { static int i = 0; if (i < 10) { printOut(i); } } int main(int argc, char *argv[]) { return 0; }
En fait, le code comstack bien avec le compilateur mingw5, ce qui est bizarre pour moi, puis je passe à Borland Comstackr, je reçois un message d’avertissement disant qu’il n’y a pas d’impression prototype de fonction, est-ce seulement un avertissement? De plus, le code s’exécute bien sans aucune fenêtre d’erreur contextuelle.
Le comportement de votre programme n’est pas défini car vous définissez printOut()
sans paramètre, mais vous l’appelez avec un seul argument. Vous devez le réparer. Mais vous l’avez écrit de manière à ce que le compilateur ne soit pas tenu de diagnostiquer le problème. (gcc, par exemple, ne met pas en garde sur le décalage des parameters, même avec -std=c99 -pedantic -Wall -Wextra
-O3.)
Les raisons en sont historiques.
Pre-ANSI C (avant 1989) n’avait pas de prototypes; les déclarations de fonction n’ont pas pu spécifier le type ou le nombre d’arguments attendus. La définition de fonction, en revanche, spécifiait les parameters de la fonction, mais pas d’une manière que le compilateur pourrait utiliser pour diagnostiquer les appels incompatibles. Par exemple, une fonction avec un paramètre int peut être déclarée (par exemple, dans un fichier d’en-tête) comme ceci:
int plus_one();
et défini (par exemple, dans le fichier .c correspondant) comme ceci:
int plus_one(n) int n; { return n + 1; }
Les informations de paramètre ont été enterrées dans la définition.
ANSI C a ajouté des prototypes, ainsi ce qui précède pourrait être écrit ainsi:
int plus_one(int n); int plus_one(int n) { return n + 1; }
Mais le langage a continué à prendre en charge les déclarations et définitions de style ancien, afin de ne pas altérer le code existant. Même la future norme C201X autorise toujours les déclarations et définitions de fonctions pré-ANSI, bien qu’elles soient obsolètes depuis 22 ans maintenant.
Dans votre définition:
void printOut() { ... }
vous utilisez une définition de fonction de style ancien. Cela dit que printOut n’a pas de paramètre – mais il ne laisse pas le compilateur vous avertir si vous l’appelez incorrectement. Dans votre fonction, vous l’appelez avec un seul argument. Le comportement de cet appel n’est pas défini . Il pourrait discrètement ignorer les arguments superflus – ou alors, il serait concevable de corrompre la stack et de provoquer la mort horrible de votre programme. (Ce dernier est peu probable; pour des raisons historiques, la plupart des conventions d’appel du C tolèrent de telles erreurs.)
Si vous voulez que votre fonction printOut () n’ait pas de paramètre et que le compilateur se plaint si vous l’appelez incorrectement, définissez-le comme suit:
void printOut(void) { ... }
C’est la seule et unique manière correcte de l’écrire en C.
Bien sûr, si vous faites simplement cette modification dans votre programme puis ajoutez un appel à printOut()
dans main()
, vous aurez une boucle récursive infinie entre vos mains. Vous voulez probablement que printOUt()
prenne un argument int
:
void printOut(int n) { ... }
En l’occurrence, C ++ a des règles différentes. C ++ est dérivé de C, mais avec moins de souci de compatibilité ascendante. Lorsque Stroustrup a ajouté des prototypes au C ++, il a complètement abandonné les déclarations à l’ancienne. Etant donné qu’il n’était pas nécessaire de disposer d’un marqueur void
spécial pour les fonctions void printOut()
paramètre, void printOut()
en C ++ indique explicitement que printOut
n’a pas de paramètre et qu’un appel avec arguments est une erreur. C ++ autorise également void printOut(void)
pour la compatibilité avec C, mais ce n’est probablement pas très souvent utilisé (il est rarement utile d’écrire un code à la fois valide C et valide C ++.) C et C ++ sont deux langages différents; Vous devez suivre les règles pour la langue que vous utilisez.
En C, une fonction sans aucun paramètre peut toujours prendre des parameters.
C’est pourquoi il comstack. La manière de spécifier qu’il ne prend aucun paramètre est la suivante:
void printOut(void)
C’est la bonne façon de le faire, mais elle est moins courante, surtout pour ceux qui ont un arrière-plan C ++.