Gibt es einen Unterschied zwischen foo (void) und foo () in C ++ oder C?

253

Betrachten Sie diese beiden Funktionsdefinitionen:

void foo() { }

void foo(void) { }

Gibt es einen Unterschied zwischen diesen beiden? Wenn nicht, warum ist das voidArgument dort? Ästhetische Gründe?

Landon
quelle
Für C ist das Q / A hier
Antti Haapala

Antworten:

317

In C :

  • void foo()bedeutet "eine Funktion, foodie eine nicht spezifizierte Anzahl von Argumenten vom nicht spezifizierten Typ nimmt"
  • void foo(void)bedeutet "eine Funktion fooohne Argumente"

In C ++ :

  • void foo()bedeutet "eine Funktion fooohne Argumente"
  • void foo(void)bedeutet "eine Funktion fooohne Argumente"

Durch das Schreiben foo(void)erreichen wir daher die gleiche Interpretation in beiden Sprachen und machen unsere Header mehrsprachig (obwohl wir normalerweise einige weitere Dinge mit den Headern tun müssen, um sie wirklich sprachübergreifend zu machen, nämlich sie in eine zu packen, extern "C"wenn wir sie kompilieren C ++).

DrPizza
quelle
10
Aber wenn C ++ das benötigt voidhätte, hätte es das Problem der "ärgerlichsten Analyse" vermeiden können.
Adrian McCarthy
5
Stimmt, aber es gibt so viele andere beschissene Parses in C ++, dass es keinen Sinn macht, über einen von ihnen zu kvetchen.
DrPizza
16
Auf eine aktuelle Frage hat @James Kanze einen interessanten Leckerbissen gepostet. Repost hier, um zu vermeiden, dass es verloren geht: In den ersten Versionen von C konnte die Anzahl der Parameter, die eine Funktion annehmen könnte, nicht angegeben werden. Dies void foo()war die einzige Syntax, die eine Funktion deklarierte. Bei der Einführung von Signaturen musste das C-Komitee den No-Parameter von der alten Syntax unterscheiden und die void foo(void)Syntax einführen . C ++ hat es aus Kompatibilitätsgründen verwendet.
Matthieu M.
3
Können Sie mir ein Beispiel für C C90 und höher geben, bei dem die Verwendung void foo()anstelle von C void foo(void)einen funktionalen Unterschied erzeugt? Dh ich benutze die Version seit vielen Jahren ohne die Leere und habe kein Problem gesehen, vermisse ich etwas?
Chacham15
6
@ chacham15 wird void foo() { if ( rand() ) foo(5); } kompiliert und ausgeführt (was zu undefiniertem Verhalten führt, es sei denn, Sie haben großes Glück), während void foo(void)bei demselben Text ein Kompilierungsfehler auftreten würde.
MM
39

Mir ist klar, dass sich Ihre Frage auf C ++ bezieht, aber wenn es um C geht, finden Sie die Antwort in K & R, Seiten 72-73:

Wenn eine Funktionsdeklaration keine Argumente enthält, wie in

double atof();

auch das bedeutet, dass über die Argumente von atof nichts anzunehmen ist; Alle Parameterprüfungen sind deaktiviert. Diese besondere Bedeutung der leeren Argumentliste soll es älteren C-Programmen ermöglichen, mit neuen Compilern zu kompilieren. Aber es ist eine schlechte Idee, es mit neuen Programmen zu verwenden. Wenn die Funktion Argumente akzeptiert, deklarieren Sie diese. Wenn keine Argumente erforderlich sind, verwenden Sie void.

Kyle Cronin
quelle
Die Frage bezieht sich jedoch auf Definitionen. In diesem Fall lautet die relevante C-Regel. Eine leere Liste in einem Funktionsdeklarator, die Teil einer Definition dieser Funktion ist, gibt an, dass die Funktion keine Parameter hat.
Jinawee
9

C ++ 11 N3337 Standardentwurf

Es gibt keinen Unterschied.

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

Anhang C "Kompatibilität" C.1.7 Abschnitt 8: Die Anmelder sagen:

8.3.5 Änderung: In C ++ akzeptiert eine mit einer leeren Parameterliste deklarierte Funktion keine Argumente. In C bedeutet eine leere Parameterliste, dass Anzahl und Typ der Funktionsargumente unbekannt sind.

Beispiel:

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

Begründung: Dies dient dazu, fehlerhafte Funktionsaufrufe zu vermeiden (dh Funktionsaufrufe mit der falschen Anzahl oder Art von Argumenten).

Auswirkung auf das ursprüngliche Merkmal: Wechseln Sie zur Semantik eines genau definierten Merkmals. Diese Funktion wurde in C als "veraltet" markiert.

8.5.3 Funktionen sagt:

4. Die Parameterdeklarationsklausel bestimmt die Argumente, die angegeben werden können, und deren Verarbeitung, wenn die Funktion aufgerufen wird. [...] Wenn die Parameterdeklarationsklausel leer ist, akzeptiert die Funktion keine Argumente. Die Parameterliste (void) entspricht der leeren Parameterliste.

C99

Wie in C ++ 11 erwähnt, int f()gibt es nichts über die Argumente an und ist veraltet.

Es kann entweder zu Arbeitscode oder UB führen.

Ich habe den C99-Standard ausführlich interpretiert unter: https://stackoverflow.com/a/36292431/895245

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

In C verwenden Sie eine Leere in einer leeren Funktionsreferenz, sodass der Compiler einen Prototyp hat und dieser Prototyp "keine Argumente" hat. In C ++ müssen Sie dem Compiler nicht mitteilen, dass Sie einen Prototyp haben, da Sie den Prototyp nicht auslassen können.

Paul Tomblin
quelle
1
"Prototyp" bezeichnet die Argumentlistendeklaration und den Rückgabetyp. Ich sage das, weil "Prototyp" mich verwirrt hat, was Sie zuerst gemeint haben.
Zan Lynx