Zawsze uważałem, że argc
jest wymagane do oznaczenia końca argv
, ale właśnie dowiedziałem się, że z definicji jest to argv[argc] == NULL
. Czy mam rację sądząc, że argc
jest całkowicie zbędny? Jeśli tak, zawsze uważałem, że C
został zrekompensowany w imię wydajności. Czy moje założenie jest błędne, czy też istnieje jakiś historyczny powód? Jeśli przyczyna jest historyczna, czy możesz ją rozwinąć?Dlaczego main (int argc, char * argv []) przyjmuje dwa argumenty?
Odpowiedz
Historia.
Harbison & Stali (5th Edition, 9.9 "Program główny") mówi, co następuje:
standardowa C wymaga
argv[argc]
być zerowy wskaźnik, ale nie jest tak w niektórych starszych implementacjach.
Byłoby pomocne wskazanie, które "starsze implementacje" nie mają "argv [argc]" jako wartości zerowej wskaźnik - podejrzewam, że H & S nie zapewnia tego poziomu szczegółowości. W dzisiejszych czasach musieli być dość starzy. (Nigdy nie miałem pecha, żeby się z nim spotkać, ale jest mnóstwo ezoterycznych platform, na których nie programowałem.) –
FWIW Udało mi się znaleźć zeskanowany plik PDF z K & R 1st ed., I o ile wiem, nigdy nie wspominaj o zerowym wskaźniku w argv [argc] ', a wszystkie przykłady używają' argc' do określenia końca tablicy 'argv []'. Druga edycja wskazuje zerowy wartownik, ale nie używa go w żadnych przykładach. –
Oto historia.
W pierwszym wydaniu UNIX, który poprzedza C, exec jako argumenty wzięła nazwę pliku oraz adres listy wskaźników do zakończonych znakami NUL łańcuchów argumentów zakończonych wskaźnikiem NULL. Od strony man:
sys exec; name; args /exec = 11.
name: <...\0>
...
args: arg1; arg2; ...; 0
arg1: <...\0>
...
Jądro zliczane argumenty i dostarczył nowy obraz z liczby arg następuje lista wskaźników do kopii ciągi argumentów, na szczycie stosu. Od strony man:
sp--> nargs
arg1
...
argn
arg1: <arg1\0>
...
argn: <argn\0>
(źródło jądra here; ja nie patrzył, czy jądro rzeczywiście napisał coś po wskaźnik do ostatniego argumentu.)
W pewnym momencie, w górę w szóstej edycji, dokumentacja dla exec, execl i execv zaczęła zauważać, że jądro umieściło -1
po wskaźnikach arg. Strona człowiek mówi:
argv nie jest bezpośrednio wykorzystywane w innym execv, ponieważ argv [argc] jest -1, a nie 0.
W tym momencie, można argumentować, że argc
był zbędny, ale programy od jakiegoś czasu używały go zamiast przeglądać listę argumentów dla -1
. Na przykład, oto początek cal.c:
main(argc, argv)
char *argv[];
{
if(argc < 2) {
printf("usage: cal [month] year\n");
exit();
}
W 7. edycji, exec została zmieniona, aby dodać wskaźnik NULL po strunach argumentów, a to nastąpiło listy wskaźników do ciągów środowiskowych, a inny NULL . Strona człowiek mówi:
argv jest bezpośrednio wykorzystywane w innym execv ponieważ argv [argc] 0.
Nie można 'NULL' być elementem' argv'? To znaczy przed faktycznym zakończeniem tablicy. –
@AndrasDeak, nie sądzę. Element 'argv' może być pustym łańcuchem, czyli tablicą jednego elementu,' 0'-bajtu. –
Tak, jest zbędny. Powód jest "historyczne powody" –