W wielu językach, takich jak C, C ++ i Java, main
metoda / funkcja ma typ zwracany void
lub int
, ale nie double
lub String
. Jakie mogą być tego przyczyny?
Wiem trochę, że nie możemy tego zrobić, ponieważ main
jest wywoływana przez bibliotekę wykonawczą i oczekuje pewnej składni, jakoś tak int main()
czy inaczej int main(int,char**)
, musimy się do tego trzymać.
Więc moje pytanie brzmi: dlaczego main
ma podpis typu, który ma, a nie inny?
Odpowiedzi:
Zwracana wartość
main
ma być przekazywana do systemu operacyjnego ( dowolnego systemu operacyjnego) w jeden, spójny sposób. Informacje, które musi znać system operacyjny to „czy program zakończył się pomyślnie, czy wystąpił błąd?”Jeśli jest to ciąg znaków, odpowiedź staje się trudna w różnych językach. Elementy wewnętrzne łańcucha Pascal (pierwszy bajt to długość) i łańcucha FORTRAN (ustalony, uzupełniony do pewnej wartości) i łańcuch C (zakończony zerem) są różne. Utrudnia to zwracanie spójnej wartości systemowi operacyjnemu. Zakładając, że problem został rozwiązany, co byś zrobił, aby odpowiedzieć na pytanie, jakie system operacyjny ma na temat programu? Porównywanie ciągów jest obarczone błędami („sukces” vs. „sukces”) i chociaż błąd może być bardziej użyteczny dla człowieka, trudniej jest poradzić sobie z systemem operacyjnym lub innym programem (powłoką). Istniały również znaczne różnice nawet w samych ciągach - EBCDIC (ze wszystkimi stronami kodowymi) w porównaniu z ASCII.
Liczba zmiennoprzecinkowa i liczba podwójna nie dostarczają żadnej dodatkowej wartości ponad liczbę całkowitą do przesyłania danych zwrotnych do systemu operacyjnego (i powłoki). W większości przypadków żadna z tych części komputera nie zajmuje się liczbami zmiennoprzecinkowymi. Nie można również wyliczyć liczby podwójnej, co utrudnia porównania. Nie można ich wyliczyć, dlatego zgłaszają, jaki był błąd (zakładając, że wybrałeś określoną wartość sukcesu). Ponownie, zmiennoprzecinkowe nie są spójne - zmiennoprzecinkowa na maszynie 8-bitowej była inna niż zmiennoprzecinkowa na maszynie 16-bitowej i 32-bitowej (i to tylko te „normalne” - nawet w IBM, zmiennoprzecinkowa nie była znormalizowana między maszynami tego samego producenta do lat osiemdziesiątych). A potem masz komputery dziesiętne kontra binarne. Wartości zmiennoprzecinkowe nie są spójne i nie dostarczają istotnych danych z powrotem.
To naprawdę pozostawia nam bajt i liczbę całkowitą jako opcje. Konwencja, która została ustanowiona jako „0”, była sukcesem, a wszystko inne było błędem. Liczba całkowita daje więcej miejsca niż bajt na zgłoszenie błędu. Można go wyliczyć (powrót 1 oznacza XYZ, powrót 2 oznacza ABC, powrót 3, oznacza DEF itp.) Lub można go użyć jako flagi (
0x0001
oznacza to,0x0002
że się nie powiedzie, oznacza, że się nie powiedzie,0x0003
oznacza to to i to, co się nie powiedzie). Ograniczenie tego do bajtu może z łatwością zabraknąć flag (tylko 8), więc prawdopodobnie zdecydowano się na użycie liczby całkowitej.źródło
main()
jest wywoływany na różne sposoby w różnych systemach operacyjnych. W C jak początkowo wywoływana jest metoda main ()? wchodzi w to.main
- w przeciwieństwie do innych funkcji w dowolnym programie - nie jest częścią protokołu zdefiniowanego przez programistę, ale protokół używany do komunikacji z hostem (OS). Nie możesz go wybrać, ponieważ nigdy nie był twój. Na bardziej pragmatycznym poziomie, UNIX oczekuje, że int zostanie zwrócony przez proces, więc protokół C-to-UNIX robi dokładnie to. Analogiczny argument można podać dla przekazywania argumentów: jeśli C został wynaleziony dla systemu operacyjnego / hosta, który przekazał tylko liczby jako argumenty (np. Bez wiersza poleceń), argumentami byłyby liczby całkowite zamiast ciągów.Cóż, może .
Na przykład w dialekcie C używanym w systemie operacyjnym Plan 9
main
jest zwykle deklarowany jakovoid
funkcja, ale status wyjścia jest zwracany do środowiska wywołującego poprzez przekazanie wskaźnikaexits()
funkcji do funkcji. Pusty ciąg oznacza sukces, a każdy niepusty ciąg oznacza pewne niepowodzenie. To mógłby być realizowany poprzezmain
zwracachar*
wynik.I z pewnością byłoby możliwe wdrożenie systemu ze statusem
float
lubdouble
zakończeniem.Więc dlaczego
int
? To tylko kwestia konwencji - a ogromną wartość ma to, że działające pod nimi systemy operacyjne i programy podlegają wspólnej konwencji.Konwencja uniksowa polega na użyciu kodu statusu liczby całkowitej, przy czym zero oznacza sukces i niezerowy błąd oznaczający (ponieważ zazwyczaj jest tylko jeden sposób na sukces, ale wiele sposobów na porażkę). Nie wiem, czy ta konwencja pochodzi od Uniksa; Podejrzewam, że pochodzi z wcześniejszych systemów operacyjnych.
Zmienna zmiennoprzecinkowa byłaby trudniejszą konwencją, ponieważ (a) obsługa zmiennoprzecinkowa nie jest uniwersalna, (b) trudniej jest zdefiniować odwzorowanie między wartościami zmiennoprzecinkowymi a warunkami błędu, (c) różne systemy używają różnych zmiennoprzecinkowych reprezentacje punktów i (d) wyobraź sobie zabawę ze śledzenia błędu zaokrąglania w statusie wyjścia z programu. Z drugiej strony liczby całkowite bardzo dobrze nadają się do wyliczania kodów błędów.
Jak już wspomniałem, Plan 9 używa ciągów, ale narzuca to pewną złożoność zarządzania pamięcią, kodowania znaków itp. O ile wiem, był to nowy pomysł, kiedy Plan 9 go zaimplementował i nie zastąpił istniejącego powszechna konwencja.
(Nawiasem mówiąc, w C ++
main
można tylko powrócićint
, a w Cvoid main
jest dozwolone tylko wtedy, gdy kompilator specjalnie go obsługuje. Wiele kompilatorów nie narzeka zbyt głośno, jeśli piszeszvoid main
, ale tylko niewielką przesadą jest stwierdzenie, że jest źle .)źródło
Wartość zwracana przez metodę główną to „kod wyjścia”. Jest używany przez aplikację wywołującą (zwykle bash), aby sprawdzić, czy program zakończył się zgodnie z oczekiwaniami. Zwracanie liczby całkowitej jest najłatwiejszym sposobem na zrobienie tego na poziomie systemu operacyjnego. Double nie ma sensu dla kodu błędu, a String jest trudny do utrzymania na poziomie systemu operacyjnego (nie ma GC).
źródło