2015-08-13 12 views
10

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?

+1

Nie można 'NULL' być elementem' argv'? To znaczy przed faktycznym zakończeniem tablicy. –

+4

@AndrasDeak, nie sądzę. Element 'argv' może być pustym łańcuchem, czyli tablicą jednego elementu,' 0'-bajtu. –

+4

Tak, jest zbędny. Powód jest "historyczne powody" –

Odpowiedz

6

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.

+0

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.) –

+0

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. –

3

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.

Powiązane problemy