Я всегда думал, что argc
должен был помечать конец argv
, но я только что узнал, что argv[argc] == NULL
по определению. Правильно ли я считаю, что argc
полностью избыточен? Если это так, я всегда думал, что C
убрали избыточность во имя эффективности. Является ли мое предположение неправильным или существует историческая причина этого? Если причина историческая, вы можете уточнить?Почему main (int argc, char * argv []) принимает два аргумента?
ответ
История.
Harbison & стали (5-е издание, 9,9 «Основная программа») говорит следующее:
Стандартный C требует, чтобы
argv[argc]
быть пустой указатель, но это не так в некоторых старых реализациях.
Было бы полезно иметь некоторые указания о том, какие «более старые реализации» не имеют 'argv [argc]' как null указатель. Я подозреваю, что H & S не обеспечивает этот уровень детализации. В эти дни они должны быть довольно старыми. (Мне никогда не приходилось сталкиваться с одним, но есть множество эзотерических платформ, на которые я не запрограммирован.) –
FWIW Мне удалось найти отсканированный PDF-файл K & R 1st ed., И насколько я могу судить, они никогда не упоминайте нулевой сторожевой указатель в 'argv [argc]', и все примеры используют 'argc', чтобы определить его конец массива' argv [] '. В 2-м издании указывается нулевой контрольный сигнал, но он не используется в каких-либо примерах. –
Вот история.
В первом выпуске 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.
- 1. int main (int argc, char * argv []) почему argc дает 2 аргумента?
- 2. Использование int main (int argc, char ** argv) в C++
- 3. Обход «int main (int argc, char ** argv)» в SDL2
- 4. Откуда это объявление: main _2a ((argc, argv), int argc, char * argv [])
- 5. Что означает int argc, char * argv []?
- 6. C++ (int getopt (argc, (char **) argv, optstring)
- 7. C++ int main (int argc, char * argv []) - массив argv a c?
- 8. как определить количество аргументов при использовании int main (int argc, char * argv [])
- 9. int main argc количество аргументов
- 10. Почему MPI_Init принимает указатели на argc и argv?
- 11. Что касается 'основного (INT ARGC, символ * ARGV [])'
- 12. call main (argc, argv) from fork()
- 13. Что такое GTEST_API_ в GTEST_API_ int main (int argc, char ** argv) {}?
- 14. C++ int main (int argc, char * argv []) аргументы преобразуются в целые значения
- 15. Глобальный охват char * argv [] и int argc C++
- 16. C++ - Должен ли argv [] в int main всегда иметь тип char * (или char **, если используется argv)?
- 17. C++ - INT основной (интермедиат ARGC, символ * ARGV [])
- 18. Проблемы argc argv
- 19. Переменные (argc, argv) для функции as (argv, argc) внутри main в C++
- 20. символ ** в Int основных (INT ARGC, символ ** ARGV)
- 21. Использование аргумента char argv [] в системе()
- 22. ошибки сегментации и ARGV, ARGC
- 23. argv [argc] ==?
- 24. «argc, argv» отсутствует в CodeBlocks
- 25. Строительство argv и argc
- 26. Значение ARGC и ARGV в междунар основной (INT ARGC, символ ** ARGV) в OpenCV
- 27. C++ argv индексы больше argc
- 28. Проблема с argc и argv
- 29. Пропуски «argc» как «argv» приводят к сравнению между char ** и int - почему?
- 30. как запустить C++ с Int основной (INT ARGC, символ * ARGV [])
Не удалось 'NULL' быть элементом' argv'? То есть до фактического конца массива. –
@ AndrasDeak, я так не думаю. Элементом 'argv' может быть пустая строка, которая представляет собой массив только одного элемента,' 0'-байт. –
Да, это избыточно. Причина в том, что «исторические причины» –