Der Abschnitt $ 3.6.1 / 1 aus dem C ++ Standard lautet:
Ein Programm muss eine globale Funktion namens main enthalten , die den festgelegten Start des Programms darstellt.
Betrachten Sie nun diesen Code,
int square(int i) { return i*i; }
int user_main()
{
for ( int i = 0 ; i < 10 ; ++i )
std::cout << square(i) << endl;
return 0;
}
int main_ret= user_main();
int main()
{
return main_ret;
}
Dieser Beispielcode macht das, was ich beabsichtige, dh das Quadrat der ganzen Zahlen von 0 bis 9 drucken, bevor er in die main()
Funktion eingeht, die der "Start" des Programms sein soll.
Ich habe es auch mit der -pedantic
Option GCC 4.5.0 kompiliert. Es gibt keinen Fehler, nicht einmal Warnung!
Meine Frage ist also:
Ist dieser Code wirklich standardkonform?
Wenn es standardkonform ist, macht es dann nicht ungültig, was der Standard sagt? main()
ist kein Start dieses Programms! user_main()
vor dem ausgeführt main()
.
Ich verstehe, dass zum Initialisieren der globalen Variablen zuerst main_ret
die use_main()
Ausführung ausgeführt wird, aber das ist eine ganz andere Sache. der Punkt ist , dass es nicht die zitierte Aussage $ 3.6.1 / 1 von der Norm ungültig, da main()
nicht das ist Start des Programms; es ist das in der Tat Ende von diesem Programm!
BEARBEITEN:
Wie definieren Sie das Wort "Start"?
Es läuft auf die Definition des Ausdrucks "Programmstart" hinaus . Wie genau definieren Sie es?
main()
als "Start des Programms"static
Lagerdauer, und als solche, diese Objekte zu verschiedenen Übersetzungseinheiten gehören , können initialisiert werden , in jeder Reihenfolge (weil die Reihenfolge ist nicht spezifiziert in der Norm). Ich bin mir nicht sicher, ob das Ihre Frage beantwortet, obwohl ich das im Zusammenhang mit diesem Thema sagen könnte.Sie lesen den Satz falsch.
Der Standard definiert das Wort "Start" für den Rest des Standards. Es heißt nicht, dass kein zuvor ausgeführter Code
main
aufgerufen wird. Es heißt, dass der Start des Programms als an der Funktion liegend angesehen wirdmain
.Ihr Programm ist konform. Ihr Programm wurde erst "gestartet", wenn main gestartet wurde. Der Konstruktor wird aufgerufen, bevor Ihr Programm gemäß der Definition von "start" im Standard "startet", aber das spielt kaum eine Rolle. Eine Menge Code wird ausgeführt , bevor
main
wird immer in jedem Programm genannt, nicht nur dieses Beispiel.Zu Diskussionszwecken wird Ihr Konstruktorcode vor dem 'Start' des Programms ausgeführt, und dies entspricht vollständig dem Standard.
quelle
Ihr Programm wird nicht verlinkt und daher nicht ausgeführt, es sei denn, es gibt eine Hauptleitung. Main () bewirkt jedoch nicht den Start der Ausführung des Programms, da Objekte auf Dateiebene Konstruktoren haben, die zuvor ausgeführt werden, und es möglich wäre, ein gesamtes Programm zu schreiben, das seine Lebensdauer ausführt, bevor main () erreicht wird, und main selbst zu lassen ein leerer Körper.
Um dies zu erzwingen, müssten Sie in der Realität ein Objekt haben, das vor main und seinem Konstruktor erstellt wurde, um den gesamten Programmfluss aufzurufen.
Schau dir das an:
Der Ablauf Ihres Programms würde sich effektiv aus ergeben
Foo::Foo()
quelle
Sie haben die Frage ebenfalls mit "C" markiert. Wenn Sie also streng über C sprechen, sollte Ihre Initialisierung gemäß Abschnitt 6.7.8 "Initialisierung" des ISO C99-Standards fehlschlagen.
Das relevanteste in diesem Fall scheint die Einschränkung Nr. 4 zu sein, die besagt:
Die Antwort auf Ihre Frage lautet also, dass der Code nicht dem C-Standard entspricht.
Sie möchten wahrscheinlich das "C" -Tag entfernen, wenn Sie nur am C ++ - Standard interessiert sind.
quelle
Abschnitt 3.6 als Ganzes ist sehr klar über das Zusammenspiel
main
und die dynamischen Initialisierungen. Der "festgelegte Start des Programms" wird nirgendwo anders verwendet und beschreibt lediglich die allgemeine Absicht vonmain()
. Es macht keinen Sinn, diesen einen Satz normativ zu interpretieren, was den detaillierteren und klareren Anforderungen des Standards widerspricht.quelle
Der Compiler muss häufig Code vor main () hinzufügen, um standardkonform zu sein . Weil der Standard vorschreibt, dass die Initialisierung von Globals / Statics erfolgen muss, bevor das Programm ausgeführt wird. Gleiches gilt für Konstruktoren von Objekten, die im Dateibereich (Globals) platziert sind.
Damit wird die ursprüngliche Frage ist relevant für C als auch, weil in einem C - Programm , das Sie noch die Globals / statische Initialisierung zu tun haben würden , bevor das Programm gestartet werden kann.
Die Standards gehen davon aus, dass diese Variablen durch "Magie" initialisiert werden, da sie nicht angeben, wie sie vor der Programminitialisierung festgelegt werden sollen. Ich denke, sie haben das als etwas angesehen, das außerhalb des Geltungsbereichs eines Programmiersprachenstandards liegt.
Bearbeiten: Siehe zum Beispiel ISO 9899: 1999 5.1.2:
Die Theorie, wie diese "Magie" ausgeführt werden sollte, reicht bis in die Geburt von C zurück, als es sich um eine Programmiersprache handelte, die nur für das UNIX-Betriebssystem auf RAM-basierten Computern verwendet werden sollte. Theoretisch wäre das Programm in der Lage, alle vorinitialisierten Daten aus der ausführbaren Datei in den RAM zu laden, während das Programm selbst in den RAM hochgeladen wurde.
Seitdem haben sich Computer und Betriebssystem weiterentwickelt, und C wird in einem weitaus größeren Bereich als ursprünglich angenommen verwendet. Ein modernes PC-Betriebssystem verfügt über virtuelle Adressen usw., und alle eingebetteten Systeme führen Code aus dem ROM und nicht aus dem RAM aus. Es gibt also viele Situationen, in denen der RAM nicht "automatisch" eingestellt werden kann.
Außerdem ist der Standard zu abstrakt, um etwas über Stapel und Prozessspeicher usw. zu wissen. Diese Dinge müssen ebenfalls ausgeführt werden, bevor das Programm gestartet wird.
Daher verfügt so ziemlich jedes C / C ++ - Programm über einen Init / "Copy-Down" -Code, der ausgeführt wird, bevor main aufgerufen wird, um den Initialisierungsregeln der Standards zu entsprechen.
Beispielsweise verfügen eingebettete Systeme normalerweise über eine Option namens "Nicht ISO-konformer Start", bei der die gesamte Initialisierungsphase aus Leistungsgründen übersprungen wird und der Code dann direkt von main startet. Solche Systeme entsprechen jedoch nicht den Standards, da Sie sich nicht auf die Init-Werte globaler / statischer Variablen verlassen können.
quelle
Ihr "Programm" gibt einfach einen Wert aus einer globalen Variablen zurück. Alles andere ist Initialisierungscode. Somit gilt der Standard - Sie haben nur ein sehr triviales Programm und eine komplexere Initialisierung.
quelle
main () ist eine Benutzerfunktion, die von der C-Laufzeitbibliothek aufgerufen wird.
Siehe auch: Vermeiden des Haupt- (Einstiegspunkts) in einem C-Programm
quelle
Scheint wie ein englischer Semantik-Streit. Das OP bezeichnet seinen Codeblock zuerst als "Code" und später als "Programm". Der Benutzer schreibt den Code und der Compiler schreibt das Programm.
quelle
main wird aufgerufen, nachdem alle globalen Variablen initialisiert wurden.
Was der Standard nicht spezifiziert, ist die Reihenfolge der Initialisierung aller globalen Variablen aller Module und statisch verknüpften Bibliotheken.
quelle
Ja, main ist der "Einstiegspunkt" jedes C ++ - Programms, mit Ausnahme implementierungsspezifischer Erweiterungen. Trotzdem passieren einige Dinge vor main, insbesondere die globale Initialisierung, wie zum Beispiel für main_ret.
quelle