Warum gibt main hier nicht 0 zurück?

Lesezeit: 5 Minuten

Benutzeravatar von Jeegar Patel
Jeegar Patel

Ich habe gerade gelesen

ISO/IEC 9899:201x Committee Draft – 12. April 2011

in dem ich unter 5.1.2.2.3 Programmabbruch gefunden habe

..reaching the } that terminates the main function returns a value of 0. 

es bedeutet, wenn Sie keine return-Anweisung in angeben main()und wenn das Programm erfolgreich ausgeführt wird, gibt die schließende geschweifte Klammer } von main 0 zurück.

Aber im folgenden Code gebe ich keine return-Anweisung an, aber es gibt nicht 0 zurück

#include<stdio.h>
int sum(int a,int b)
{
return (a + b);
}

int main()
{
    int a=10;
    int b=5;
    int ans;    
    ans=sum(a,b);
    printf("sum is %d",ans);
}

kompilieren

gcc test.c  
./a.out
sum is 15
echo $?
9          // here it should be 0 but it shows 9 why?

  • +1 für die Geduld, Spezifikationen zu lesen …..

    – Ascher

    30. Dezember 2011 um 8:42 Uhr

  • gcc selbst (für Version 4.6.2) kompiliert eine Sprache, die C sehr ähnlich ist, aber nicht ganz wie C. Es kompiliert GnuC89 — eine Sprache, die “lose” auf C89 basiert.

    – pmg

    30. Dezember 2011 um 8:45 Uhr


  • Die Klammern auf der return Aussage ein sum() sind unnötig. int main() sollte sein int main(void).

    – Keith Thompson

    30. Dezember 2011 um 8:47 Uhr

  • Verwirrung != Tippfehler. Auf meiner Tastatur sind ‘0’ und ‘o’ nahe genug, dass es leicht letzteres sein kann. 😉

    – Die 111

    30. Dezember 2011 um 9:09 Uhr

  • IMHO ist eine ziemlich dumme Spezifikation, da sie den Compiler zwingt, die “main”-Funktion auf besondere Weise zu verwalten, indem ein implizites “return 0” hinzugefügt wird. Eine Funktion namens “main” verhält sich also etwas anders. Was ist mit den Überprüfungen zur Kompilierzeit (“kein Rückgabewert” und ähnliches)?

    – Giuseppe Guerrini

    30. Dezember 2011 um 12:29 Uhr

Benutzeravatar von cnicutar
Cnicutar

Diese Regel wurde in der Version 1999 des C-Standards hinzugefügt. In C90 ist der zurückgegebene Status undefiniert.

Sie können es aktivieren, indem Sie übergeben -std=c99 zu gcc.

Als Randnotiz wird interessanterweise 9 zurückgegeben, weil es die Rückgabe von ist printf die nur 9 Zeichen geschrieben hat.

  • Oder Sie können einfach hinzufügen return 0; vor der Schließung }. Es ist harmlos und macht Ihr Programm auf ältere Compiler portierbar.

    – Keith Thompson

    30. Dezember 2011 um 8:46 Uhr

  • @Mr.32: gute Beobachtung, printf() gibt die Länge der Zeichenfolge zurück, also ist es 9, was die “Rückgabe” der Hauptdatei ist (ohne Verwendung von -std=c99).

    – Hicham

    30. Dezember 2011 um 9:16 Uhr

  • @cnicutar: Funktionen geben normalerweise keine kleinen Werte auf dem Stapel zurück – da dies eher einen Pop, einen Push und einen Sprung als nur eine Bewegung und eine Rückkehr beinhalten würde – es handelt sich also mit ziemlicher Sicherheit um ein Register. eax speziell auf x86.

    – Jon Purdy

    30. Dezember 2011 um 9:37 Uhr

  • Ja, die x86-API gibt normalerweise einen ganzzahligen Wert über die zurück eax registrieren. Sehen en.wikipedia.org/wiki/X86_calling_conventions#cdecl für mehr Informationen.

    – Sylvain Defresne

    30. Dezember 2011 um 10:04 Uhr

  • Ich habe mehrmals Code wie “int foo(void) { bar(); }” gesehen, wo “return bar()” beabsichtigt war. Dieser Code funktioniert trotz des offensichtlichen Fehlers auf den meisten Prozessoren einwandfrei.

    – ugoren

    3. Januar 2012 um 19:51 Uhr

Es gibt den Rückgabewert von zurück printf Das ist die Anzahl der tatsächlich ausgedruckten Zeichen.

  • Die Frage spricht nicht darüber, was in der Konsole gedruckt wird, wenn das Programm ausgeführt wird, sondern über den Rückgabewert des Programms: (Sie können es unter Linux mit dem Schell-Befehl abrufen: echo $? und unter Windows mit: echo %errorlevel% )

    – Hicham

    30. Dezember 2011 um 9:10 Uhr

  • @eharvest Obwohl ich nicht weiß, wie ich das überprüfen soll %errorlevel% in Windows jeder Unterschied zwischen Exit-Code und Rückgabewert von main unter linux?

    – Sommer_Mehr_Mehr_Tee

    30. Dezember 2011 um 9:33 Uhr

  • @eharvest: Die Antwort spricht nicht darüber, was auch in der Konsole gedruckt wird. Es spricht über die Rückgabewert von printf was in diesem Fall 9 ist, die dann als Exit-Code von “befördert” wird main irgendwie bei der Verwendung bestimmter gcc-Versionen.

    – AH

    30. Dezember 2011 um 9:47 Uhr

  • Verzeihung. mein Fehler. Sie haben Recht. Ich habe diese Antwort zu schnell gelesen :/

    – Hicham

    30. Dezember 2011 um 9:53 Uhr


  • Beachten Sie, dass dies der Fall ist nicht garantiert. In C89/C90 ist der in diesem Fall zurückgegebene Status nicht definiert; es könnte alles sein. Es wird zufällig 9 zurückgegeben, weil der Compiler keine Anstrengungen unternommen hat, etwas anderes zurückzugeben. Andere Compiler werden sich wahrscheinlich anders verhalten.

    – Keith Thompson

    30. Dezember 2011 um 20:31 Uhr

Der Rückgabewert einer Funktion wird normalerweise im eax-Register der CPU gespeichert, daher wird die Anweisung “return 4;” würde normalerweise zu kompilieren

mov eax, 4;
ret;

und return x (abhängig von Ihrem Compiler) wäre so etwas wie:

mov eax, [ebp + 4];
ret;

Wenn Sie keinen Rückgabewert angeben, spuckt der Compiler immer noch das “ret” aus, ändert aber nicht den Wert von eax. Der Aufrufer wird also denken, dass das, was vorher im eax-Register verblieben ist, der Rückgabewert ist. In diesem Beispiel wäre es normalerweise der Rückgabewert printf, aber unterschiedliche Compiler generieren unterschiedlichen Maschinencode und verwenden einige Register unterschiedlich.

Dies ist eine vereinfachte Erklärung, unterschiedliche Aufrufkonventionen und Zielplattformen spielen eine wichtige Rolle, aber es sollten genügend Informationen sein, um zu erklären, was in Ihrem Beispiel „hinter den Kulissen“ passiert.

Wenn Sie ein grundlegendes Verständnis von Assembler haben, lohnt es sich, die Disassemblierung verschiedener Compiler zu vergleichen. Möglicherweise stellen Sie fest, dass einige Compiler das eax-Register als Sicherheitsmaßnahme löschen.

  • Der Compiler könnte TU das. Es ist undefiniert. Es kann sich stattdessen dafür entscheiden, Ihnen mit einer Druckerpatrone in den Kopf zu schießen.

    – Leichtigkeitsrennen im Orbit

    3. Januar 2012 um 18:01 Uhr


  • @LightnessRacesinOrbit undefined ist nicht dasselbe wie unvorhersehbar, dh aus “wenn der Compiler X macht, wird er standardkonform sein” folgt nicht logisch “der Compiler könnte X machen”

    – Owen

    23. November 2013 um 2:09 Uhr

  • @Owen: Zitieren Sie die Standardpassage, die dies definiert.

    – Leichtigkeitsrennen im Orbit

    23. November 2013 um 4:12 Uhr

  • @LightnessRacesinOrbit Es tut mir leid, dass ich nicht ganz folgen kann. Ich denke, was ich wirklich sagen möchte, ist, dass ich denke, dass Einblicke unter die Haube wie noggin182, die in dieser Antwort bereitgestellt werden, unglaublich nützlich für das Debuggen sind. Wenn Ihr Programm unerwartete Ergebnisse produziert, wissen Sie oft nicht, woher diese kommen oder wo im Code Sie suchen müssen, und ein Verständnis der Implementierungsdetails kann Sie in die richtige Richtung weisen.

    – Owen

    23. November 2013 um 5:41 Uhr

  • @Owen Ich habe nie etwas anderes behauptet

    – Leichtigkeitsrennen im Orbit

    23. November 2013 um 11:47 Uhr

1422290cookie-checkWarum gibt main hier nicht 0 zurück?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy