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_SUCCESSa EXIT_FAILUREjako 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_SUCCESSdo 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_FAILUREna 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.