Wer erhält den von main () zurückgegebenen Wert?

34

Ich weiß, dass bei Computern der von der main()Funktion zurückgegebene Wert vom Betriebssystem empfangen wird. Aber was passiert in der main()Funktion eines Mikrocontrollers?

user18118
quelle
7
Ich verwende immer void main (), wenn ich C für PIC-Mikrocontroller verwende. Bei der Verwendung von C-Compilern für Mikrocontroller spielt das eigentlich keine Rolle. Weil es kein Betriebssystem gibt, auf dem "main.c" ausgeführt wird. Wenn in diesem Mikrocontroller so etwas wie RTOS ausgeführt wird, ist das Betriebssystem "main.c".
Abdullah Kahraman
4
Nicht wirklich ein Duplikat, aber zumindest verwandt: electronics.stackexchange.com/q/30830/4950
PetPaulsen
1
Wie die Startfunktion definiert ist, liegt in der Regel nicht bei Ihnen. Die von Ihnen verwendete Umgebung dokumentiert die unterstützten Formulare für Startfunktionen. Hosted C-Implementierungen müssen zwei Formen mainmit zwei unterschiedlichen Signaturen unterstützen, die beide zurückgeben int. Wenn Sie eine freistehende C-Implementierung verwenden, bestimmt diese Implementierung, wie Sie die Startfunktion schreiben sollen. Sie können keine voidRückgabefunktion schreiben, nur weil sie nicht zurückgegeben wird. Das Verhalten von nicht wiederkehr unterscheidet sich von der Funktion Typ , die die Gesamt-Aufrufkonventionen beeinflusst.
Kaz

Antworten:

42

Auf einem Mikrocontroller main()wird nicht erwartet, dass er jemals beendet wird, und das Verhalten ist nicht definiert - es liegt also an dem, der die C-Laufzeit für den Mikrocontroller geschrieben hat. Ich habe Systeme gesehen, die:

  • Führen Sie eine implizite Schleife durch main(), damit sie beim Beenden einfach erneut aufgerufen wird.
  • Erstellen Sie eine einfache "Sprung zu sich selbst" -Schleife, die ausgeführt wird, wenn sie main()jemals beendet wird.
  • Führen Sie einfach den Rest des Codespeichers aus, der auf den Aufruf von folgt main(). Dies nennt man "ins Unkraut laufen".

Ich habe noch nie einen gesehen, der überhaupt etwas mit dem von zurückgegebenen Wert macht main(). Wenn Ihnen dies wirklich wichtig ist, sollten Sie sich den Quellcode für die C-Laufzeitbibliothek Ihres Systems ansehen und möglicherweise ändern.

Dave Tweed
quelle
1
Du warst schneller als ich. +1 für Synchronität.
Adam Lawrence
9
Der C-Standard, main()der einen intRückgabewert definiert, wurde offensichtlich nicht für einen Mikrocontroller ohne Betriebssystem entwickelt. Dies ist also ein unspezifiziertes Verhalten und abhängig von Ihrer C-Laufzeit kann alles passieren, wie Dave aufgelistet hat.
22.
4
C, das auf einem betriebssystemlosen Mikrocontroller ausgeführt wird, kann als eigenständige Implementierung betrachtet werden, und der C-Standard erfordert nicht einmal eine eigenständige Umgebung, um einen main()Rückgabewert zu definieren, geschweige denn , ihn zu definieren. Das liegt beim Implementierer.
KutuluMike
2
@ndim - um Haare zu teilen, void main( void )ist die Implementierung definiertes Verhalten , nicht unspezifiziertes Verhalten .
Andrew
1
@ MichaelEdenfield: In der Tat. Der gesamte Code in C ist jedoch in Bezug auf Funktionen definiert, sodass es niemals möglich ist, ein aktuelles System vollständig in C zu schreiben. Es muss mindestens ein kleines Stück Assembler-Sprache (oder was auch immer) vorhanden sein, das eine minimale Umgebung einrichtet, damit eine C-Funktion aufgerufen werden kann. Der offensichtlichste Name für diese Funktion ist main().
Dave Tweed
5

Ein häufiges Missverständnis / Mythos ist, dass dies int maindie einzige gültige Form ist, die in der Norm festgelegt ist. Das ist nicht wahr.

Der C-Standard spricht von zwei Implementierungen: gehostet und freistehend. "Implementierung" bedeutet in diesem Fall Compiler. Gehostete Compiler kompilieren für ein bestimmtes Betriebssystem und freistehende Compiler kompilieren für eine bestimmte Bare-Metal-Anwendung. Eingebettete Systeme sind fast immer freistehende Systeme - auch im Fall von RTOS.

Für freistehende Implementierungen kann jede Form verwendet main()werden. Sie müssen nicht einmal eine Funktion namens main haben. Meistens verwenden sie das Formular void main (void), da es keinen Sinn macht, etwas zurückzugeben.

Was hier zu beachten ist, ist, dass immer der Compiler die Form bestimmt main()und niemals der Programmierer.

Freistehende Implementierungen , die tun von der Rückgabe etwas main()sehr fraglich. Sie wundern sich, ob die Leute, die den Compiler erstellt haben, tatsächlich den Standard gelesen haben ...

Details hier .

Lundin
quelle
3

Der C-Sprachstandard erlaubt die Implementierung definierter Variationen void main( void )und dies ist die übliche Form in eingebetteten Systemen - einfach, weil nicht erwartet wird, dass sie zurückkehren.

Wenn Sie sich das Compiler-Setup ansehen, gibt es normalerweise ein Bootstrap-Code-Snippet, das vom Reset-Vektor aufgerufen wird und eine grundlegende Initialisierung (einschließlich z. B. Kopieren von Initialisierungswerten in Variablen) vor dem Aufrufen von main () durchführt.

Dies wird sich (normalerweise) auch in einer Endlosschleife befinden oder möglicherweise einen Reset durchführen, wenn es main()zurückkehrt

Andrew
quelle
0

Es hängt (wie andere Antworten bereits sagten) von Ihrer Toolchain ab, wird aber zum Beispiel in GCC mainals andere Funktionen kompiliert, so dass sein Rückgabewert entsprechend den Aufrufkonventionen gespeichert wird (auf ARM verwende ich direkt nicht mit GCC, es wird auf R0 gesetzt) kurz vor der Rückkehr).

Ich vermute, dass dies bei AVR-GCC ähnlich ist, sodass benutzerdefinierte Skripte diesen Wert nach den Hauptrückgaben verwenden können.

kwesolowski
quelle
das geht am eigentlichen Punkt vorbei
Chris Stratton
Es wird betont, dass derjenige, der anruft main, seinen Rückgabewert erhalten kann. Natürlich wird es in 99,9% Situationen ignoriert, aber answer gibt es Informationen darüber, wer diesen Rückgabewert erhalten kann.
Kwesolowski