À la fois le Standard C99 (6.7.5.3) et la Norme C11 (6.7.6.3) état:
Une liste d'identifiants déclare seulement les identifiants des paramètres
de la fonction. Une liste vide dans une fonction de demande de déclaration qui est de la partie
d'une définition de cette fonction indique que la fonction n'a pas de
les paramètres. La liste vide dans une fonction de demande de déclaration qui n'est pas partie
d'une définition de cette fonction spécifie qu'aucun d'informations sur
le nombre ou le type des paramètres est fournie.
Depuis la déclaration de foo est une partie de la définition, de la déclaration
spécifie que les foo prend 0 arguments, donc, l'appel foo(str) est à
moins moralement mauvais. Mais comme décrit ci-dessous, il existe différents
degrés de "mauvais" dans C, et les compilateurs peuvent diffèrent dans la façon dont ils traitent
avec certains types de "mauvais".
Pour prendre un peu plus simple exemple, considérons le programme suivant:
int f() { return 9; }
int main() {
return f(1);
}
Si je compile le dessus à l'aide de Clang:
tmp$ cc tmp3.c
tmp3.c:4:13: warning: too many arguments in call to 'f'
return f(1);
~ ^
1 warning generated.
Si je compile avec gcc 4.8 je n'ai pas d'erreurs ou d'avertissements, même avec le Mur. Une réponse précédente a suggéré d'utiliser -Wstrict-prototypes, ce qui indique correctement que la définition de f n'est pas sous forme de prototype, mais ce n'est vraiment pas le point. La Norme(s) de permettre la définition d'une fonction dans une non-forme de prototype tel que celui ci-dessus et les Normes clairement que cette définition indique que la fonction prend 0 arguments.
Maintenant, il y a une contrainte (C11 Sec. 6.5.2.2):
Si l'expression qui désigne la fonction appelée a un type qui comprend un prototype, le nombre d'arguments est d'accord avec le nombre de paramètres.
Cependant, cette contrainte ne s'applique pas dans ce cas, puisque le type de la fonction ne pas inclure un prototype. Mais ici, c'est un rapport suivant dans la sémantique de l'article (et pas une "contrainte"), qui ne s'appliquent:
Si l'expression qui désigne la fonction appelée a un type qui ne comprend pas un prototype
... Si le nombre d'arguments n'est pas égal au nombre de paramètres, le comportement est indéfini.
D'où l'appel de fonction n'entraîner un comportement non défini (c'est à dire, le programme n'est pas "strictement conforme"). Cependant, la Norme ne nécessite une mise en œuvre de signaler un message de diagnostic quand une réelle contrainte est violée, et dans ce cas, il n'y a pas de violation d'une contrainte. Donc gcc n'est pas nécessaire de signaler une erreur ou un avertissement pour être "conforme mise en œuvre".
Donc, je pense que la réponse à la question, pourquoi ne gcc permet-il?, est que gcc n'est pas nécessaire de déclarer quoi que ce soit, puisque ce n'est pas une violation de contrainte. En outre gcc n'a pas la prétention de faire rapport à chaque type de comportement indéfini, même avec un Mur ou -Wpedantic. C'est un comportement indéfini, ce qui signifie la mise en œuvre peut choisir la façon de traiter avec elle, et la gcc a choisi de le compiler sans avertissements (et apparemment, il ignore l'argument).