Czy exit () robi coś specjalnego, czego nie robi „return”?
W przypadku niektórych kompilatorów dla nietypowych platform exit()
może tłumaczyć swój argument na wartość wyjściową programu, podczas gdy zwrot z main()
może po prostu przekazać wartość bezpośrednio do środowiska hosta bez żadnego tłumaczenia.
Standard wymaga identycznego zachowania w tych przypadkach (konkretnie, to mówi powrocie coś, co jest int
-Kompatybilny ze main()
powinno być równoznaczne z wywołaniem exit()
tej wartości). Problem polega na tym, że różne systemy operacyjne mają różne konwencje interpretowania wartości wyjściowych. W wielu systemach (WIELE!) 0 oznacza sukces, a wszystko inne jest porażką. Ale przy, powiedzmy, VMS, nieparzyste wartości oznaczają sukces, a nawet te oznaczają porażkę. Jeśli zwróciłeś 0 zmain()
, użytkownik VMS zobaczy nieprzyjemną wiadomość o naruszeniu dostępu. W rzeczywistości nie doszło do naruszenia praw dostępu - był to po prostu standardowy komunikat związany z kodem błędu 0.
Potem przyszedł ANSI i pobłogosławił, EXIT_SUCCESS
a EXIT_FAILURE
jako argumenty można przekazać exit()
. Norma mówi również, że exit(0)
należy zachowywać się identycznie exit(EXIT_SUCCESS)
, więc większość implementacji zdefiniować EXIT_SUCCESS
do 0
.
Dlatego standard wprowadza cię w VMS, ponieważ nie pozostawia żadnego standardowego sposobu na zwrócenie kodu błędu , który ma wartość 0.
Kompilator VAX / VMS C z wczesnych lat 90. nie interpretował zatem wartości zwracanej main()
, po prostu zwracał dowolną wartość do środowiska hosta. Ale jeśli go użyjesz exit()
, zrobi to, czego wymaga standard: przetłumacz EXIT_SUCCESS
(lub 0
) na kod sukcesu i EXIT_FAILURE
na ogólny kod błędu. Aby użyć EXIT_SUCCESS
, trzeba było przekazać go exit()
, z którego nie można było go zwrócić main()
. Nie wiem, czy nowsze wersje tego kompilatora zachowały to zachowanie.
Przenośny program C wyglądał tak:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Hello, World!\n");
exit(EXIT_SUCCESS); /* to get good return value to OS */
/*NOTREACHED*/ /* to silence lint warning */
return 0; /* to silence compiler warning */
}
Na bok: jeśli dobrze pamiętam, konwencja VMS dla wartości wyjściowych jest bardziej szczegółowa niż nieparzysta / parzysta. W rzeczywistości używa czegoś takiego jak trzy niskie bity do kodowania poziomu ważności. Ogólnie jednak, nieparzyste poziomy dotkliwości wskazywały na sukces lub różne informacje, a parzyste wskazywały błędy.