Właśnie czytałem
ISO / IEC 9899: Projekt Komisji 201x - 12 kwietnia 2011 r
w którym znalazłem w punkcie 5.1.2.2.3 Zakończenie programu
..reaching the } that terminates the main function returns a value of 0.
oznacza to, że jeśli nie określisz żadnej instrukcji return w main()
i program zostanie uruchomiony pomyślnie, to w nawiasie zamykającym} main zwróci 0.
Ale w poniższym kodzie nie określam żadnej instrukcji return, ale nie zwraca ona 0
#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);
}
skompilować
gcc test.c
./a.out
sum is 15
echo $?
9 // here it should be 0 but it shows 9 why?
gcc
samodzielnie (dla wersji 4.6.2) kompiluje język bardzo podobny, ale nie całkiem podobny do C. Kompiluje GnuC89 - język „luźno” oparty na C89.return
wyciągu wsum()
są niepotrzebne.int main()
powinno byćint main(void)
.Odpowiedzi:
Zasada ta została dodana w wersji normy C. z 1999 roku. W C90 zwracany status jest niezdefiniowany.
Możesz to włączyć, przechodząc
-std=c99
do gcc.Na marginesie, co ciekawe, zwrócono 9, ponieważ jest to powrót,
printf
który właśnie napisał 9 znaków.źródło
return 0;
przed zamknięciem}
. Jest nieszkodliwy i sprawia, że program można przenosić na starsze kompilatory.eax
szczególnie na x86.eax
rejestru liczby całkowite, takie jak wartość . Więcej informacji można znaleźć pod adresem en.wikipedia.org/wiki/X86_calling_conventions#cdecl .Zwraca wartość,
printf
która jest liczbą rzeczywiście wydrukowanych znaków.źródło
%errorlevel%
w systemie Windows, jest jakaś różnica między kodem zakończenia a wartością zwracaną w systemiemain
Linux?printf
którym w tym przypadku jest 9, który następnie pobiera „promowane” jako kod wyjścia zmain
jakoś podczas korzystania z niektórych wersjach GCC.Wartość zwracana przez funkcję jest zwykle przechowywana w rejestrze eax procesora, więc instrukcja „return 4;” zwykle kompilowałby się do
a zwrot x (w zależności od kompilatora) wyglądałby tak:
jeśli nie określisz wartości zwracanej, kompilator nadal będzie wypluwał „ret”, ale nie zmieni wartości eax. Więc dzwoniący pomyśli, że to, co zostało wcześniej w rejestrze eax, jest wartością zwracaną. W tym przykładzie byłaby to zwykle wartość zwracana printf, ale różne kompilatory generują inny kod maszynowy i inaczej używają niektórych rejestrów.
To jest uproszczone wyjaśnienie, różne konwencje wywoływania i platformy docelowe będą odgrywać istotną rolę, ale powinno to wystarczyć do wyjaśnienia, co dzieje się „za kulisami” w twoim przykładzie.
Jeśli masz podstawową wiedzę na temat asemblera, warto porównać dezasemblację różnych kompilatorów. Może się okazać, że niektórzy kompilatorzy czyszczą rejestr eax jako zabezpieczenie.
źródło