Wird nach einer Funktionsdeklaration in C ++ kein Semikolon (';') benötigt?

174

Ich habe kürzlich einen Zwischenprogrammiertest gemacht und eine der Fragen, die ich falsch gestellt habe, war folgende:

Ein Semikolon (';') wird nach einer Funktionsdeklaration nicht benötigt.

Richtig oder falsch.

Ich entschied mich für „falsch“ (und bitte korrigieren Sie mich , wenn ich falsch bin , weil ich fühle , dass ich verrückt werde), eine Funktion Erklärung ist , was Sie vor der Definition schreiben (am Anfang des Codes) so dass der Compiler die Funktion kennt rufen , bevor sogar nennen es, und eine Funktion Definition ist es, was die Funktion als Ganzes bildet.

Dh

Erklärung:

int func();

Definition:

int func() {
  return 1;
}

Sollte die Antwort darauf nicht falsch sein?

Logan
quelle
41
Eine Definition ist auch eine Erklärung. Aber ich würde sagen, Ihre Antwort war richtig.
216
Es ist eine knifflige Frage und hat keinen Einfluss auf die Fähigkeit eines jeden, gut zu programmieren.
Phonetagger
40
Ich finde die Fragen, die zu Doppel-Negativen führen, immer verwirrend. In meinen Augen sollen solche Fragen die Schüler stolpern lassen. Warum konnte die Frage nicht folgendermaßen formuliert werden: "Nach einer Funktionsdeklaration wird immer ein Semikolon (';') benötigt. Richtig oder falsch."? : /
Algirdas Preidžius
18
@phonetagger All diese Verwirrung zeigt, wie schlecht die Frage formuliert ist.
François Andrieux
34
Hanlons Rasiermesser schlägt vor, dass der Autor des Tests "Deklaration" und "Definition" verwechselt.
Sneftel

Antworten:

161

Es kann vorkommen, dass Sie die Funktion in einem Schritt deklarieren und definieren, dh wenn Sie die Funktionsdefinition an der Stelle einfügen, an der Sie sie deklarieren. So technisch nehme ich wahr richtig ist. Aber die Frage ist so formuliert, dass ich sie so beantwortet hätte, wie Sie es getan haben.

jwismar
quelle
10
Ich würde argumentieren, dass wahr aus dem von Ihnen angegebenen Grund nicht korrekt ist. Wenn es Fälle gibt, in denen ein Semikolon benötigt wird, ist es falsch (oder nicht wahr). Wahr ist für mich das Absolute. Wenn es klare Fälle gibt, in denen es gebraucht wird, kann man nicht wahr sagen.
Ich Funball
16
@IFunball Gutes Argument. Dumme Muttersprachen. Der Satz "Ein Semikolon (';') wird nach einer Funktionsdeklaration nicht benötigt" kann gelesen werden als "Ein Semikolon (';') wird nach einer Funktionsdeklaration (nie) nicht benötigt" oder als "Ein Semikolon (';') ) wird nach einer Funktionsdeklaration nicht (immer) benötigt ". Ob die Aussage als wahr oder falsch eingestuft werden soll, hängt von der Wahl einer Interpretation ab. Genau genommen ist die Frage unklar und hat daher keine klare Antwort.
Peter - Stellen Sie Monica
6
@IFunball Es liegt daran, dass "Deklaration" ohne weiteren Kontext und ohne Aussage, dass wir Sprachjuristen sind, gemeinhin als "nicht definierende Deklaration" verstanden wird. Die Frage war unfair.
Leichtigkeitsrennen im Orbit
2
Jede Prüfungsfrage, die jemandem unklar ist, der den zu testenden Inhalt kennt, ist fehlerhaft.
Nat
2
Klingt so, als müssten wir der englischen Sprache eine undefinierte Verhaltensklausel hinzufügen
Nick Mertin
147

Zusätzlich zu der Sache "Eine Definition ist auch eine Deklaration" ist Folgendes legal C ++:

int f(), g();

Dies deklariert zwei Funktionen, fund zwar gsowohl ohne Argumente als auch mit einem Rückgabetyp von int, aber der Definition von ffolgt nicht (sofort) ein Semikolon. Ebenso ist dies legal:

int f(), i = 42;

In diesen Fällen darf das Semikolon jedoch nicht vollständig weggelassen werden. Daher wäre es etwas überraschend, wenn eines der beiden Beispiele als Beispiel für eine Deklaration ohne nachfolgendes Semikolon herangezogen würde. In der Tat ist Folgendes illegal:

void *p, f() {}

Anders als eine (nur) Funktionsdeklaration, eine Funktion Definition kann nicht mit anderen Erklärung oder Definition derselben kombiniert werden Typ-Spezifizierer . (Wenn dies legal wäre, würde es sowohl a void *pals auch a definieren void f() {}.)

In jedem Fall scheint dies eine Art "Gotcha" -Frage zu sein, die nicht in einem Zwischenprogrammiertest enthalten sein sollte.

(Oh, übrigens, bitte schreibe keinen Code wie int f(), i = 42;.)

Arne Vogel
quelle
2
Es ist auch möglich, ein typedef zu verwenden, um einen Funktionstyp zu definieren, und dieses dann zu verwenden, um viele Funktionen gleichzeitig zu deklarieren. typedef int fooProc(int); fooProc a,b.c.d.e;Ich bin mir beispielsweise nicht sicher, warum Standard-Header für Compiler auf Diskettenlaufwerk dies in der Vergangenheit nicht getan haben Tag, da ich denken würde, dass Header-Dateien viel kleiner und damit schneller zu verarbeiten gewesen wären.
Supercat
Beachten Sie auch, dass int f(int(&g)(),int(*h)()){return g()+h();}dies drei Funktionsdeklarationen hat, von denen eine von einer offenen geschweiften Klammer, eine von einem Komma und eine dritte von einer engen Klammer gefolgt wird.
David Hammen
1
@DavidHammen: Das deklariert keine anderen Funktionen als int f(stuff). Auch im Funktionsumfang gist eine automatische Variable vom Typ auf Funktion verweisen und hein Zeiger auf Funktion .
Peter Cordes
83

Die anderen Antworten und Kommentare zeigen einige der vielen Möglichkeiten auf, dass dies eine schreckliche, irreführende und schlecht geschriebene Frage ist. Aber es gibt noch ein anderes Problem, das noch niemand identifiziert hat. Die Frage ist:

Ein Semikolon (';') wird nach einer Funktionsdeklaration nicht benötigt. Richtig oder falsch.

OK, schauen wir uns eine Funktionsdeklaration an:

int func();       /* */
/*           ^       */
/*           |       */
/* That whitespace is "after the function declaration". */

Das Ganze ist die Erklärung . Die Erklärung wird nicht int func()und dann gefolgt von ein ;. Auf die Deklaration int func();folgt ein Leerzeichen.

Die Frage ist also: Wird nach der Deklaration ein Semikolon benötigt ? Natürlich nicht. Die Deklaration enthält bereits ein Semikolon, das sie beendet hat. Ein Semikolon nach der Deklaration wäre sinnlos. Im Gegensatz,int func(); ; wäre ein Semikolon nach einer Funktionsdeklaration .

Die Frage war mit ziemlicher Sicherheit bestimmt „: ist die letzte Token in einer Funktionsdeklaration immer ein Semikolon wahr oder falsch“ Aber das ist nicht die Frage , die sie geschrieben hat , weil der Autor des Quiz war nicht klar , über das Problem zu denken , die Frage zu stellen.

Mein Rat ist, Programmiersprachen-Quiz insgesamt zu vermeiden. Sie sind ziemlich schrecklich.


Lustige Tatsache, während wir auf dem Thema sind. In C # sind diese alle legal:

class C {}
class D {};
struct E {}
struct F {};

In C # kann eine Klassen- oder Strukturdeklaration nach Ihrem Ermessen mit einem Semikolon enden oder nicht. Diese seltsame kleine Funktion wurde für C / C ++ - Programmierer hinzugefügt, die zu C # kommen und wissen, dass Typdeklarationen mit einem sinnlosen Semikolon enden. Das Designteam wollte sie nicht dafür bestrafen, dass sie diese Angewohnheit hatten. :-)

Eric Lippert
quelle
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Samuel Liew
25

Sie können eine Funktion auch wie folgt deklarieren:

int func(){
    return 1;
}

Die Aussage ist sehr vieldeutig. Die richtige Antwort sollte lauten: Es hängt davon ab, wie Sie die Funktion deklarieren.

Wie auch immer, ich hätte auch falsch gewählt, und vielleicht können Sie die Frage jemandem melden.

Luca Corsini
quelle
3
Wie auch immer, stellen Sie das Ding nicht auf eine persönliche Ebene. Das Wichtigste ist, dass Sie verstanden haben, wie eine Funktionsdeklarationsdefinition funktioniert. Machen Sie sich also keine allzu großen Sorgen. Stellen Sie nur sicher, dass die Frage mindestens überprüft wird, und fahren Sie fort
Luca Corsini,
11
Absolut. Ehrlich gesagt habe ich mehr über die Definition von Funktionsdeklarationen gelernt, indem ich die Frage falsch gestellt habe, als ich es richtig verstanden hätte.
Logan
1
@Logan mach dir keine Sorgen. Wenn Sie wissen, wie man eine Funktion schreibt und liest, ist das alles, was Sie brauchen. Ich persönlich hasse solche Fragen, die 1. nicht genau definiert sind 2. Ihre theoretischen Kenntnisse der Syntax testen. Für mich ist es wie ein Muskelgedächtnis. Wenn ich schreibe, geht jede Ziffer mühelos auf die Taste, die sie gehen soll, aber wenn Sie mir einen Test darüber geben, welche Tasten eine Ziffer drücken sollte, wäre ich ohne Tastatur völlig hoffnungslos, um die Aktion physisch
auszuführen
2
... Das Schreiben einer allgemeinen Syntax (z. B. einer Funktion) wird für Sie zur zweiten Natur. Und wenn Sie es vermasseln, weil Sie gerade die Sprache gewechselt haben, dann sorgen Intellisense und Syntaxhervorhebung für schnelle und effiziente Lösungen. Investieren Sie Ihre Zeit und Energie in etwas Nützlicheres.
Bolov
20

Ein Semikolon (';') wird nach einer Funktionsdeklaration nicht benötigt.

Richtig oder falsch.

Stimmt . Nach einer Deklaration wird kein Semikolon benötigt. Noch nach irgendeiner Definition. Noch nach irgendeiner Aussage.

Viele Arten von Deklarationen müssen mit einem Semikolon enden, wie in der Syntax in Abschnitt 7 [dcl.dcl] angegeben. Aber danach muss nie mehr ein zweiter geschrieben werden.

Marc van Leeuwen
quelle
1
Ich sehe, dass Eric Lippert diesen Punkt bereits argumentiert hat. Ich denke, all die positiven Stimmen haben mich dazu gebracht, es zu übersehen. Fühlen Sie sich frei, Ihre Stimmen dort abzugeben.
Marc van Leeuwen
So ziemlich jede Frage, die fragt: "X ist immer wahr: wahr oder falsch?" wird die Antwort "falsch" haben. Es ist nirgendwo nötig , ein Semikolon zu haben . Der Compiler kann sich beschweren und sich weigern, Ihr Programm zu kompilieren, aber das ist kaum das Ende der Welt. Ich würde es nicht als Grundbedürfnis bezeichnen . ;)
Quuxplusone
@Quuxplusone Wenn der Compiler Ihr Programm ablehnt, enthält Ihr Programm keine Funktionsdeklarationen :)
Ben Millwood
6

Dies hängt davon ab, ob wir die Funktion deklarieren oder definieren. Wenn wir die Funktion deklarieren, müssen wir das Semikolon ( ;) einfügen , und wenn wir die Funktion definieren, wird das Semikolon nicht benötigt.

Eine Erklärung lautet wie folgt:

int add(int, int);

Und eine Definition ist wie folgt:

int add(int a, int b)
{
    // ...
}
Rocx En Ruff
quelle
10
Das Problem bei dieser Antwort ist, dass Definitionen und Deklarationen sich gegenseitig ausschließen. Tatsächlich ist jede Definition eine Erklärung; Definitionen sind eine Teilmenge von Deklarationen.
MSalters
6

Auch wenn ich fast allen anderen Antworten zustimme und feststelle, dass die Frage sehr vieldeutig ist und Ihre Antwort technisch korrekt ist, kann ich eine andere Perspektive geben:

So habe ich sie immer genannt:

void func();  // The function prototype

...

void func()
{
    // The function definition
}

Ich gehe davon aus, dass die Frage unter Berücksichtigung dieser Terminologie gestellt wurde.

Definition und Erklärung sind in meinen Augen dasselbe Konzept. "Ich definiere x = y" == "Ich deklariere x = y".

Aber natürlich gibt es einen großen Unterschied zwischen dem Funktionsprototyp (oben) und der tatsächlichen Definition der Funktion.

Opifex
quelle
Für mich ist Ihr Prototyp die Erklärung, die darauf basiert, wie ich gelernt habe (ohne zu sagen, dass Sie sich auch irren), aber dann würde ich auch erwarten, dass ein Prototyp die Anzahl und Art der Argumente angibt oder nichtig ist, aber ich gehe davon aus, dass Sie dies weggelassen haben der Kürze halber.
David S
David S: Ja, natürlich würde es auch die Anzahl und Art der Argumente enthalten, aber ich habe sie der Kürze halber weggelassen (beachten Sie, dass die eigentliche Funktionsdeklaration auch keine Argumente enthält). Ich stimme jedoch nicht wirklich zu, wenn Sie sagen, dass die vollständige Funktionsdeklaration als Prototyp bezeichnet wird. Ich zitiere Wikipedia: "Ein Funktionsprototyp oder eine Funktionsschnittstelle ist eine Deklaration einer Funktion, die den Namen und die Typensignatur der Funktion (Arität, Datentypen von Parametern und Rückgabetyp) angibt, aber den Funktionskörper weglässt."
Opifex
@DavidS: In C ++ sind Funktionsdeklarationen immer Prototypen (oder Definitionen) und entsprechen void func();genau diesenvoid func(void); . Dies unterscheidet sich stark von C , wo void func();der Compiler nichts über die Argumente sagt und nicht dasselbe ist wie void func(void);. Ein späterer Prototyp oder eine spätere Definition sind eine gute Idee, andernfalls muss der Aufrufer die Standard-Arg-Promotions anwenden (z. B. float -> double und engen Integer-Typen auf int. Gleiche Regeln wie für Args auf verschiedene Funktionen.)
Peter Cordes
Ich entschuldige mich dafür, dass ich hier etwas mit C zu tun hatte und den Sprachwechsel nicht bemerkt habe. Ich werde meinen Kommentar aus Gründen der Klarheit nicht löschen, sondern als zurückgezogen betrachten.
David S
6

Schade, dass die Frage, die Sie gestellt haben, nicht "direkt danach" lautet. Wir könnten zum Beispiel folgendes schreiben:

int func()  /* My function */ ;

Oder ich könnte schreiben:

int func()
int a = 42;

Im ersten Fall steht das Semikolon nicht direkt danach der Deklaration, aber das wäre in Ordnung.

Im zweiten Fall steht ein Semikolon "nach" der Deklaration, jedoch nicht direkt danach.

Ich denke, Eric Lippert hat die richtige Idee in seiner Antwort .

Es ist wie zu sagen "sollte es einen Punkt nach dem Ende eines Satzes auf Englisch geben?". Wahrscheinlich hat ein Satz bereits einen Punkt am Ende (sonst wäre es kein Satz) und daher sollte es keinen Punkt nach dem Satz geben.

Nick Gammon
quelle
4
Nett. Beenden Sie diesen Satz mit einem zusätzlichen Punkt. Ich sehe, was du dort getan hast.
David S
2
int func() int a=42;kompiliert nicht. Du brauchst ein Komma, kein anderes int. Siehe die Antwort von @ Arne, die über einen Tag zuvor veröffentlicht wurde. Das einzig Neue an dieser Antwort ist der letzte Absatz mit der Analogie zu englischen Sätzen.
Peter Cordes
1
Ich habe das zweite kompilierte Beispiel nicht gesagt. Ich wies darauf hin, dass die Aussage, dass ein Semikolon "nach" der Erklärung erforderlich sei, nicht eindeutig sei. Mein Beispiel hatte nach der Deklaration ein Semikolon, das jedoch nicht kompiliert wird.
Nick Gammon
1
Das gleiche Problem tritt bei Fehlermeldungen auf. Ein beliebtes Beispiel aus C # ist " Ein Parameter params muss der letzte Parameter in einer formalen Parameterliste sein ". Angenommen, ich sagte stattdessen "Ein Frob muss der letzte Gloob in einer Gloob-Liste sein". Bedeutet dies (1) Jede Gloob-Liste hat genau einen Frob am Ende, so wie jede Frage genau ein Fragezeichen am Ende hat. (2) Eine Gloob-Liste kann eine beliebige Anzahl von Frobs haben, aber wenn sie einen oder mehrere Frobs hat , der letzte Gegenstand muss ein Frob sein, so wie eine gerade Zahl eine beliebige Zahl von 02468 haben kann, aber einer der muss der letzte sein, oder ...
Eric Lippert
... (3) Eine Gloob-Liste kann null oder eins Stirnrunzeln haben, und wenn sie eins hat, kommt sie am Ende? Wenn Sie den Kontext nicht kennen, würde ich denken, dass (1) die sinnvollste Erklärung ist, aber im Fall von "params parameter" ist (3) die richtige Erklärung. Viele informelle Beschreibungen von Programmiersprachenelementen haben eine Eigenschaft, die meine Freunde des technischen Editors "COIK" nennen - Nur löschen, wenn bekannt. Wenn Sie das Material noch nicht gründlich verstehen, ist eine Beschreibung für Sie nutzlos, aber wenn Sie es bereits gründlich verstehen, brauchen Sie die Beschreibung nicht!
Eric Lippert
4

Sie können ;nur für Prototypen verwenden.

M7off
quelle
4

Es ist eine knifflige Frage, aber sie haben das Wort Deklaration verwendet, was ungefähr so ​​viel bedeutet:

int example();

In diesem Fall ist es also wahr.

Wenn sie das Wort Implementierung verwendet hätten , wäre es falsch gewesen.

dark_3nergy
quelle
2

Semikolon (;) wird verwendet, um dem Compiler mitzuteilen, dass nach diesem Semikolon (;) eine neue Anweisung beginnt.

Ich denke also, dass das Semikolon (;) nur während einer Funktionsdeklaration benötigt wird. Meiner Meinung nach wird die Antwort wahr sein.

Jatinder
quelle
Erklärungen sind jedoch keine Aussagen.
HolyBlackCat
Nach der Funktionsdeklaration führen wir jedoch eine neue Codezeile mit dem Compiler aus. Daher denke ich, dass vor dem Ausführen einer neuen Codezeile der Compiler wissen muss, wo die vorherige Codezeile endet, nur dann kann ein Compiler nativen Code generieren (dh 0101).
Jatinder
2

Wenn Funktionen vor main () definiert sind :

  • Benötigen Sie kein Semikolon, da die Funktion bereits definiert ist

Wenn Funktionen nach main () definiert sind :

  • Benötigen Sie ein Semikolon, weil Sie diese Funktion prototypisieren und dem Compiler mitteilen, dass die Funktion beendet wird.
shiv shah
quelle