Warum kann main kein double oder String zurückgeben, anstatt int oder void?


38

In vielen Sprachen wie C, C ++ und Java hat die mainMethode / Funktion den Rückgabetyp voidoder int, aber nicht doubleoder String. Was könnten die Gründe dafür sein?

Ich weiß ein wenig , dass wir das nicht tun können , weil maindurch Laufzeitbibliothek aufgerufen wird , und erwartet , dass einige Syntax wie int main()oder int main(int,char**)so wir , dass bleiben haben.

Meine Frage lautet also: Warum hat maines die Typensignatur und keine andere?


15
Was würde ein doppelter Rückgabewert bedeuten ? Was würde ein String-Rückgabewert bedeuten ?

1
Ich verstehe, dass es nichts bedeutet. Aber irgendwelche anderen Gründe und Konventionen?
Java

1
Ich denke, es hat nichts zu bedeuten, einfach weil allgemein gewählt wurde, dass 0 für den normalen Ausgang und eine nicht-Null für einen abnormalen. Ein Int wurde als einfachster Datentyp mit breiter sprachübergreifender Kompatibilität gewählt. @ delnan
JAVA

@sunny Nach meiner Erfahrung mit Unix-ähnlichen Betriebssystemen wird 0 als "normaler Exit" (0 Fehler) verwendet, da es im Vergleich zu anderen Ganzzahlwerten eindeutig ist. Da die meisten (nicht alle) modernen Sprachen so gestaltet sind, dass sie C ähneln (wenn nicht auf der Rückseite), und da C zum Schreiben von Unix verwendet wurde, würde ich sagen, dass es eine historische Entscheidung von KnR war.
Jamie Taylor

3
@sunny "breite sprachübergreifende Kompatibilität" war kein Problem. C und UNIX wurden zusammen geschrieben. Viele andere Sprachen geben Ints zurück, weil sie für die Verwendung in UNIX- oder UNIX-ähnlichen Umgebungen entwickelt wurden.

Antworten:


83

Der Rückgabewert von muss mainauf eine einzige, konsistente Weise an das Betriebssystem (ein beliebiges Betriebssystem) übergeben werden. Das Betriebssystem muss wissen, ob das Programm erfolgreich beendet wurde oder ob ein Fehler aufgetreten ist.

Wenn dies eine Zeichenfolge ist, wird die Antwort in verschiedenen Sprachen schwierig. Die Interna eines Pascal-Strings (erstes Byte ist Länge) und eines FORTRAN-Strings (fest, auf einen bestimmten Wert aufgefüllt) und eines C-Strings (mit Null-Abschluss) sind alle unterschiedlich. Dies würde es schwierig machen, einen konsistenten Wert an das Betriebssystem zurückzugeben. Unter der Annahme, dass dies gelöst wurde, was würden Sie tun, um die Frage des Betriebssystems nach dem Programm zu beantworten? Zeichenfolgenvergleiche sind mit Fehlern behaftet ("Erfolg" vs "Erfolg"), und obwohl der Fehler für einen Menschen nützlicher ist, ist es für das Betriebssystem oder ein anderes Programm (Shell) schwieriger, damit umzugehen. Es gab auch signifikante Unterschiede selbst in den Zeichenfolgen - EBCDIC (mit all seinen Codepages) im Vergleich zu ASCII.

Floats und Doubles bieten über die Ganzzahl hinaus keinen zusätzlichen Wert für die Rückübertragung von Daten an das Betriebssystem (und die Shell). Zum größten Teil befasst sich keiner dieser Teile des Computers mit Gleitkommazahlen. Doppel sind auch nicht aufzählbar, was Vergleiche erschwert. Da sie nicht aufzählbar sind, geben sie an, was der Fehler war (vorausgesetzt, Sie haben einen bestimmten Wert für den Erfolg ausgewählt). Auch hier sind Gleitkommawerte nicht konsistent - ein Gleitkommawert auf einer 8-Bit-Maschine war anders als der Gleitkommawert auf einer 16-Bit- und einer 32-Bit-Maschine (und das sind nur die „normalen“) - selbst innerhalb von IBM war Gleitkomma nicht standardisiert zwischen Maschinen des gleichen Herstellers bis in die 1980er Jahre). Und dann haben Sie dezimale oder binäre Computer. Gleitkommawerte sind nicht konsistent und liefern keine aussagekräftigen Daten zurück.

Das lässt uns wirklich mit dem Byte und der Ganzzahl als Optionen. Die Konvention, die festgelegt wurde, war '0', war Erfolg, und alles andere war ein Fehler. Eine Ganzzahl bietet mehr Platz als ein Byte, um den Fehler zu melden. Es kann aufgezählt werden (Rückgabe von 1 bedeutet XYZ, Rückgabe von 2 bedeutet ABC, Rückgabe von 3 bedeutet DEF usw.) oder als Flags verwendet werden ( 0x0001bedeutet, 0x0002dass dies fehlgeschlagen ist, bedeutet, dass 0x0003dies und das fehlgeschlagen ist). Wenn Sie dies auf nur ein Byte beschränken, können die Flags leicht ausgehen (nur 8). Daher wurde wahrscheinlich die Entscheidung getroffen, eine Ganzzahl zu verwenden.


2
Ich denke, main wird von der c / c ++ - Laufzeitbibliothek aufgerufen, bevor os es aufruft.
Dies

5
main()wird auf verschiedenen Betriebssystemen auf unterschiedliche Weise aufgerufen. Wie heißt die main () -Methode in C anfangs? geht darauf ein.

22
Ich denke, dass der entscheidende Punkt zu verstehen ist, dass main- im Gegensatz zu anderen Funktionen in jedem Programm - nicht Teil eines vom Programmierer definierten Protokolls ist, sondern das Protokoll, das für die Schnittstelle zum Host (OS) verwendet wird. Sie können es nicht auswählen, weil Sie es nie ausgewählt haben. Auf einer pragmatischeren Ebene erwartet UNIX, dass ein int von einem Prozess zurückgegeben wird, und das C-zu-UNIX-Protokoll tut genau das. Für die Argumentübergabe kann ein analoges Argument angegeben werden: Wenn C für ein Betriebssystem / einen Host erfunden worden wäre, das / der nur Zahlen als Argumente übergibt (z. B. keine Befehlszeile), wären die Argumente Ints anstelle von Zeichenfolgen.
Euro Micelli

2
IBM übernahm das Konzept der Codepages von EBCDIC auf ihre PCs. Sie verfolgen uns auch heute noch, 35 Jahre nach der Einführung des IBM 5150. 7-Bit- ASCII ist codepage-frei, aber 8-Bit-Zeichencodes können je nach Einstellung auch auf einem einzelnen Computer auf viele verschiedene Arten interpretiert werden - - geschweige denn die Codepages, die für Mehrbyte-Codierungen codieren. Es ist also sogar noch schlimmer als das, worauf Sie im letzten Satz des zweiten Absatzes anspielen.
ein Lebenslauf

@EuroMicelli, das ist eine sehr nette Information, eigentlich danke dafür :)
JAVA

27

Gut könnte es .

Beispielsweise wird der im Betriebssystem Plan 9 verwendete Dialekt von C mainnormalerweise als voidFunktion deklariert , der Beendigungsstatus wird jedoch an die aufrufende Umgebung zurückgegeben, indem ein Zeichenfolgenzeiger an die exits()Funktion übergeben wird. Die leere Zeichenfolge kennzeichnet Erfolg, und jede nicht leere Zeichenfolge kennzeichnet einen Fehler. Dies hätte umgesetzt werden können, indem mainein char*Ergebnis zurückgegeben wurde.

Und es wäre sicherlich möglich, ein System mit einem floatoder einem doubleExit-Status zu implementieren .

Warum also int? Es ist nur eine Frage der Konvention - und es hat einen enormen Wert, Betriebssysteme und Programme, die unter dieser Konvention ausgeführt werden, einer gemeinsamen Konvention zu unterwerfen.

Die Unix-Konvention sieht die Verwendung eines ganzzahligen Statuscodes vor, wobei 0 für Erfolg und Nicht-Null für Misserfolg steht (da es normalerweise nur eine Möglichkeit zum Erfolg gibt, aber mehrere Möglichkeiten zum Fehlschlagen). Ich weiß nicht, ob diese Konvention von Unix stammt. Ich vermute, dass es von früheren Betriebssystemen kam.

Gleitkomma wäre eine schwierigere Konvention, da (a) Gleitkomma-Unterstützung nicht universell ist, (b) es schwieriger ist, eine Zuordnung zwischen Gleitkomma-Werten und Fehlerbedingungen zu definieren, (c) verschiedene Systeme unterschiedliche Gleitkomma- Punktdarstellungen, und (d) stellen Sie sich nur den Spaß vor, einen Rundungsfehler im Exit-Status Ihres Programms aufzuspüren. Ganzzahlen hingegen eignen sich sehr gut für die Aufzählung von Fehlercodes.

Wie ich bereits erwähnt habe, werden in Plan 9 Zeichenfolgen verwendet, was jedoch eine gewisse Komplexität für die Speicherverwaltung, die Zeichencodierung usw. mit sich bringt. Soweit ich weiß, war dies eine neue Idee, als Plan 9 sie implementierte und die vorhandene Idee nicht ersetzte weit verbreitete Konvention.

(Übrigens, in C ++ mainkann nur zurückkehren int, und in C void mainist nur zulässig , wenn der Compiler speziell unterstützt. Viele Compiler beschweren sich nicht sehr laut , wenn Sie schreiben void main, aber es ist nur eine leichte Übertreibung zu sagen , dass es falsch .)


9

Der von der main-Methode zurückgegebene Wert ist ein "Exit-Code". Es wird von der aufrufenden Anwendung (normalerweise bash) verwendet, um zu testen, ob das Programm wie erwartet beendet wurde. Die Rückgabe einer Ganzzahl ist die einfachste Methode auf Betriebssystemebene. Double macht keinen Sinn für Fehlercode und ein String ist auf Betriebssystemebene schwer zu pflegen (es gibt keinen GC).


3
Warum muss eine Zeichenfolge müllsammelbar sein, eine Ganzzahl dagegen nicht?
Brad

4
@Brad, Strings haben eine variable Länge und wären im Wesentlichen dasselbe wie das Zurückgeben eines Arrays, bei dem es sich um ein Zeichen oder um Tausende handeln könnte. Dynamisches Gedächtnis wäre ein Schmerz, während ein int eine ziemlich feste Größe hat, die nicht so schwer zu handhaben ist.
JB King
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.