Я всегда думал, что argc
должен был пометить конец argv
, но я только что узнал, что argv[argc] == NULL
по определению. Правильно ли я думаю, что argc
полностью избыточно? Если это так, я всегда думал, что C
устранено избыточность во имя эффективности. Является ли мое предположение неправильным или существует историческая причина этого? Если причина историческая, вы можете уточнить?
Почему main (int argc, char * argv []) принимает два аргумента?
Ответ 1
История.
Harbison and Steel (5th Edition, 9.9 "Основная программа" ) говорит следующее:
Стандарт C требует, чтобы
argv[argc]
был нулевым указателем, но это не так в некоторых старых реализациях.
Ответ 2
Здесь история.
В первом выпуске UNIX, который предшествует C, exec взял в качестве аргументов имя файла и адрес списка указателей на NUL- завершенные строки аргументов, завершаемые указателем NULL. На странице man:
sys exec; name; args / exec = 11.
name: <...\0>
...
args: arg1; arg2; ...; 0
arg1: <...\0>
...
Ядро подсчитывало аргументы и предоставляло новое изображение счетчику arg, за которым следует список указателей на копии строк аргументов в верхней части стека. На странице man:
sp--> nargs
arg1
...
argn
arg1: <arg1\0>
...
argn: <argn\0>
(Источник ядра здесь; я не смотрел, действительно ли ядро написало что-то после указателя на последний аргумент. )
В какой-то момент, до 6-го издания, документация для exec, execl и execv начали замечать, что ядро размещено a -1
после указателей arg. На странице руководства написано:
Argv напрямую не используется в другом execv, поскольку argv [argc] равен -1, а не 0.
В этот момент вы можете утверждать, что argc
был избыточным, но программы в течение некоторого времени использовали его, а не просматривали список аргументов для -1
. Например, здесь начало cal.c:
main(argc, argv)
char *argv[];
{
if(argc < 2) {
printf("usage: cal [month] year\n");
exit();
}
В 7-м выпуске exec было изменено, чтобы добавить указатель NULL после строк аргументов, и за ним последовал список указателей к строкам среды и другому NULL. На странице руководства написано:
Аргв напрямую можно использовать в другом execv, потому что argv [argc] равен 0.