2015-08-13 2 views
10

Я всегда думал, что argc должен был помечать конец argv, но я только что узнал, что argv[argc] == NULL по определению. Правильно ли я считаю, что argc полностью избыточен? Если это так, я всегда думал, что C убрали избыточность во имя эффективности. Является ли мое предположение неправильным или существует историческая причина этого? Если причина историческая, вы можете уточнить?Почему main (int argc, char * argv []) принимает два аргумента?

+1

Не удалось 'NULL' быть элементом' argv'? То есть до фактического конца массива. –

+4

@ AndrasDeak, я так не думаю. Элементом 'argv' может быть пустая строка, которая представляет собой массив только одного элемента,' 0'-байт. –

+4

Да, это избыточно. Причина в том, что «исторические причины» –

ответ

6

История.

Harbison & стали (5-е издание, 9,9 «Основная программа») говорит следующее:

Стандартный C требует, чтобы argv[argc] быть пустой указатель, но это не так в некоторых старых реализациях.

+0

Было бы полезно иметь некоторые указания о том, какие «более старые реализации» не имеют 'argv [argc]' как null указатель. Я подозреваю, что H & S не обеспечивает этот уровень детализации. В эти дни они должны быть довольно старыми. (Мне никогда не приходилось сталкиваться с одним, но есть множество эзотерических платформ, на которые я не запрограммирован.) –

+0

FWIW Мне удалось найти отсканированный PDF-файл K & R 1st ed., И насколько я могу судить, они никогда не упоминайте нулевой сторожевой указатель в 'argv [argc]', и все примеры используют 'argc', чтобы определить его конец массива' argv [] '. В 2-м издании указывается нулевой контрольный сигнал, но он не используется в каких-либо примерах. –

3

Вот история.

В первом выпуске UNIX, который предшествует C, exec принял в качестве аргументов имя файла и адрес списка указателей на строки аргументов с нулевым завершением, завершенные указателем NULL. От человека страница:

sys exec; name; args /exec = 11. 
name: <...\0> 
... 
args: arg1; arg2; ...; 0 
arg1: <...\0> 
... 

Ядра подсчитаны аргументов и при условии, новое изображения с графом агд следует список указателей на копию строк аргументов, в верхней части стеки. От человека странице:

sp--> nargs 
     arg1 
     ... 
     argn 

arg1: <arg1\0> 
... 
argn: <argn\0> 

(Источник ядра here, я не смотрел, чтобы увидеть, если ядро ​​действительно написал что-то после того, как указатель на последний аргумент.)

В какой-то момент, до через 6-е издание документация для exec, execl и execv начала замечать, что ядро ​​разместило -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 , Страница человек говорит:

ARGV непосредственно использовать в другом execv, потому что ARGV [ARGC] 0.

Смежные вопросы