Y a-t-il une différence entre foo (void) et foo () en C ++ ou C?

253

Considérez ces deux définitions de fonction:

void foo() { }

void foo(void) { }

Y a-t-il une différence entre ces deux? Sinon, pourquoi l' voidargument est-il là? Des raisons esthétiques?

Se poser sur
la source
Pour C, le Q / A est
Antti Haapala

Réponses:

317

En C :

  • void foo()signifie "une fonction fooprenant un nombre non spécifié d'arguments de type non spécifié"
  • void foo(void)signifie "une fonction foone prenant aucun argument"

En C ++ :

  • void foo()signifie "une fonction foone prenant aucun argument"
  • void foo(void)signifie "une fonction foone prenant aucun argument"

En écrivant foo(void), par conséquent, nous obtenons la même interprétation dans les deux langues et rendons nos en-têtes multilingues (bien que nous ayons généralement besoin de faire plus de choses aux en-têtes pour les rendre vraiment multilingues; à savoir, les envelopper dans un extern "C"si nous compilons C ++).

DrPizza
la source
10
Mais si C ++ avait exigé le void, il aurait pu éviter le problème de "l'analyse la plus vexante".
Adrian McCarthy
5
Certes, mais il y a tellement d'autres analyses merdiques en C ++, il n'y a vraiment aucun intérêt à en savoir plus sur l'une d'entre elles.
DrPizza
16
Sur une question récente, @James Kanze a publié une friandise intéressante. Republiez ici pour éviter de la perdre: les premières versions de C ne permettaient pas de spécifier le nombre de paramètres qu'une fonction pouvait prendre, void foo()c'était donc la seule syntaxe pour déclarer une fonction. Lorsque les signatures ont été introduites, le comité C a dû lever l'ambiguïté sans paramètre de l'ancienne syntaxe et a introduit la void foo(void)syntaxe. C ++ l'a pris pour des raisons de compatibilité.
Matthieu M.
3
Pouvez-vous me donner un exemple de C C90 et plus tard où l'utilisation void foo()au lieu de void foo(void)produira une différence fonctionnelle? C'est-à-dire que j'utilise la version sans vide depuis de nombreuses années et que je n'ai vu aucun problème, est-ce que je manque quelque chose?
chacham15
6
@ chacham15 void foo() { if ( rand() ) foo(5); } compile et s'exécute (provoquant un comportement indéfini sauf si vous êtes très chanceux), alors void foo(void)qu'avec le même corps, une erreur de compilation se produirait.
MM
39

Je sais que votre question concerne C ++, mais quand il s'agit de C, la réponse se trouve dans K&R, pages 72-73:

De plus, si une déclaration de fonction n'inclut pas d'arguments, comme dans

double atof();

cela signifie également qu'il ne faut rien présumer des arguments de atof; toute la vérification des paramètres est désactivée. Cette signification particulière de la liste d'arguments vide est destinée à permettre aux anciens programmes C de compiler avec de nouveaux compilateurs. Mais c'est une mauvaise idée de l'utiliser avec de nouveaux programmes. Si la fonction prend des arguments, déclarez-les; s'il ne prend aucun argument, utilisez void.

Kyle Cronin
la source
Mais la question porte sur les définitions, dans ce cas, la règle C pertinente est Une liste vide dans un déclarant de fonction qui fait partie d'une définition de cette fonction spécifie que la fonction n'a pas de paramètres.
jinawee
9

Projet standard C ++ 11 N3337

Il n'y a pas de différence.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

Annexe C "Compatibilité" C.1.7 Article 8: déclarants dit:

8.3.5 Modification: en C ++, une fonction déclarée avec une liste de paramètres vide ne prend aucun argument. En C, une liste de paramètres vide signifie que le nombre et le type des arguments de fonction sont inconnus.

Exemple:

int f();
// means int f(void) in C ++
// int f( unknown ) in C

Justification: Cela permet d'éviter les appels de fonction erronés (c'est-à-dire les appels de fonction avec le mauvais nombre ou le mauvais type d'arguments).

Effet sur l'entité d'origine: modification de la sémantique d'une entité bien définie. Cette fonctionnalité a été marquée comme «obsolète» en C.

8.5.3 fonctions dit:

4. La clause de déclaration de paramètre détermine les arguments qui peuvent être spécifiés et leur traitement lors de l'appel de la fonction. [...] Si la clause de déclaration de paramètre est vide, la fonction ne prend aucun argument. La liste de paramètres (void) est équivalente à la liste de paramètres vide.

C99

Comme mentionné par C ++ 11, int f()ne spécifie rien sur les arguments et est obsolète.

Cela peut conduire à un code de travail ou à UB.

J'ai interprété la norme C99 en détail sur: https://stackoverflow.com/a/36292431/895245

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
2

En C, vous utilisez un vide dans une référence de fonction vide afin que le compilateur ait un prototype et que ce prototype n'ait "aucun argument". En C ++, vous n'avez pas besoin de dire au compilateur que vous avez un prototype car vous ne pouvez pas laisser de côté le prototype.

Paul Tomblin
la source
1
"prototype" signifie la déclaration de la liste d'arguments et le type de retour. Je dis cela parce que "prototype" m'a confus quant à ce que vous vouliez dire au début.
Zan Lynx