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
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.
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
14222900cookie-checkWarum gibt main hier nicht 0 zurück?yes
+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 einsum()
sind unnötig.int main()
sollte seinint 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