Зачем проверять, если (* argv == NULL)?

В классе структур данных, который я сейчас беру, нам было поручено написать веб-сканер на C ++. Чтобы дать нам фору, профессор предоставил нам программу для получения источника по заданному URL-адресу и простой анализатор HTML для удаления тегов. Основная функция этой программы принимает аргументы и поэтому использует argc / argv. Код, используемый для проверки аргументов, выглядит следующим образом:

// Process the arguments
if (!strcmp(option, "-h"))
{
    // do stuff...
}
else if (!strcmp(option, ""))
{
    // do stuff...
}
else if (!strcmp(option, "-t"))
{
    // do stuff...
}
else if (!strcmp(option, "-a"))
{
    // do stuff...
}

if ( *argv == NULL )
{
    exit(1);
}

Где «option» был заполнен переключателем в argv [1], а argv [2] и выше имеет остальные аргументы. Первый блок я прекрасно понимаю, если переключатель равен строке, делайте все, что зависит от переключателя. Мне интересно, какова цель последнего блока if.

Возможно, мой C ++ несколько устарел, но я припоминаю, что * argv эквивалентен argv [0], в основном это означает, что он проверяет наличие аргументов. За исключением того, что у меня создалось впечатление, что argv [0] всегда (по крайней мере, в большинстве реализаций) содержал имя запускаемой программы. Мне приходит в голову, что argv [0] может иметь значение null, если argc равно 0, но поискав в Google, я не смог найти ни одного сообщения, определяющего, возможно ли это вообще.

И поэтому я обращаюсь к вам. Что же такое окончательная проверка блока if?

РЕДАКТИРОВАТЬ: Я придерживался рассуждений, приведенных в комментариях к выбранному ответу, о том, что можно намеренно привести к тому, что argv [0] станет NULL или иным образом станет NULL в зависимости от платформы. конкретная реализация main.


person Shaun Hamman    schedule 25.02.2010    source источник
comment
Обратите внимание, что argv не массив, а указатель. Это означает, что вы вполне можете сказать argv++, чтобы перебирать варианты. Вам не нужно изменять значение *argv.   -  person Johannes Schaub - litb    schedule 25.02.2010
comment
Из любопытства, по какой причине ваш профессор спросил его об этом?   -  person Daniel    schedule 28.04.2015
comment
Сейчас, 5 лет спустя, боюсь, я действительно не помню. Кажется, я смутно припоминаю, что спрашивал у моего ТА, и рассуждения были такими же, как и в комментариях к принятому ответу (см. РЕДАКТИРОВАНИЕ в вопросе), но я мог это выдумывать и просто вспоминать все неправильно. :П   -  person Shaun Hamman    schedule 02.05.2015
comment
Я знаю, что это действительно поздно, но, как примечание, вы можете легко проанализировать параметры командной строки с помощью getopt ().   -  person RastaJedi    schedule 20.09.2016
comment
Не уверен, что маркировка этого как дубликата была оправдана, учитывая, что этот вопрос был задан, и на него ответили за 3 месяца до связанного дубликата. (Фактически, это было 7 лет назад в этот момент ›_›)   -  person Shaun Hamman    schedule 17.02.2017


Ответы (4)


argc предоставит вам количество переданных аргументов командной строки. Вам не нужно проверять содержимое argv, чтобы убедиться, что аргументов недостаточно.

if (argc <= 1) { // The first arg will be the executable name
   // print usage
}
person mmx    schedule 25.02.2010
comment
Я знаю это, приведенный выше код - это код, который нам дал наш профессор. Лично я всегда проверяю argc. Я спрашиваю, что на самом деле проверяет * argv == NULL? У меня сложилось впечатление, что это то же самое, что и проверка argv [0] == NULL, что, насколько я знаю, невозможно, так зачем же это проверять? - person Shaun Hamman; 25.02.2010
comment
@Shaun: Да, *argv идентичен argv[0]. Обычно это невозможно, когда вы запускаете приложение из обычной оболочки. Но я думаю, что это возможно, если вы выполните процесс непосредственно из другой программы, используя exec системный вызов и передавая массивы вручную. - person mmx; 25.02.2010
comment
Я думал, что argv [0] всегда содержит имя программы, так зачем проверять, является ли оно NULL? - person Shaun Hamman; 25.02.2010
comment
@Shaun: Ну, это не волшебство, когда имя программы помещается в argv. Оболочка помещает это в массив, когда запускает ваш процесс. Возможно (в зависимости от платформы) вручную создать процесс запуска, который не передает такой аргумент вашей программе. - person mmx; 25.02.2010
comment
@Shaun: Может, ваш профессор ... не прав? - person kennytm; 25.02.2010
comment
Профессор пишет по стандарту C ++. Конечно, может случиться так, что его код полагается где-то еще на особенности реализации (например, некоторый API для подключения к сети), что, как оказывается, ограничивает код платформами, которые гарантируют, по доброте их сердец, а не по какой-либо необходимости налагается стандартом, что argv [0] не равно нулю. - person Steve Jessop; 25.02.2010
comment
@Shaun, программа могла увеличить argv, поэтому теперь она указывает на нулевой указатель. См. Ответ @ Steve. - person Johannes Schaub - litb; 25.02.2010
comment
@Mehrdad: Хорошо, я могу поверить, что можно сделать argv [0] NULL, если вы сделаете это намеренно. Просто то, что наши программы всегда запускались либо в Windows, либо в Solaris, никогда не через настраиваемую программу запуска, и никогда не видел этой проверки ни в одной из них, это показалось мне довольно странным. - person Shaun Hamman; 25.02.2010
comment
@Shaun: Можно с уверенностью предположить, что это так в нормальных обстоятельствах. Но поскольку argc специально предназначен для подсчета количества аргументов, почему вы рискуете этого не сделать? Добавление оператора if, который проверяет наличие argc, не представляет большого труда. - person mmx; 25.02.2010
comment
@Mehrdad: Я согласен, но я не писал код. :) - person Shaun Hamman; 25.02.2010

3.6.1/2:

Если argc отличен от нуля, эти аргументы должны быть предоставлены в argv [0], хотя ... и argv [0] должен быть указателем на начальный символ NTMBS, который представляет имя, используемое для вызова программа или "". Значение argc должно быть неотрицательным. Значение argv[argc] должно быть 0.

Акцент мой. argc гарантируется только неотрицательным, но не ненулевым.

Это при входе в main. Также возможно, что //do stuff изменяет значение argv или содержимое массива, на который он указывает. Для кода обработки опций не является чем-то необычным сдвигать значения с argv в процессе их обработки. Таким образом, проверка для *argv == null может быть проверкой того, остались ли какие-либо аргументы командной строки после того, как параметры были удалены или пропущены. Вам придется взглянуть на остальную часть кода.

person Steve Jessop    schedule 25.02.2010

Помня, насколько портативен C, он не всегда может работать на стандартной платформе, такой как Windows или Unix. Возможно, это какой-то микрокод внутри вашей стиральной машины, работающий в дешевой, взломанной среде. Таким образом, перед разыменованием указателя рекомендуется убедиться, что указатель не равен нулю, что могло привести к вопросу.

Тем не менее, вы правы. * argv совпадает с argv [0], а argv предполагается инициализируется средой, если это предусмотрено.

person Walt Stoneburner    schedule 25.02.2010
comment
«Возможно, это какой-то микрокод внутри вашей стиральной машины» - отлично, теперь я жду сообщения. Извините, вы должны обновить «Adobe Flash» до последней версии, чтобы войти в цикл полоскания. - person Tom West; 25.02.2010

просто предположение.

что, если ваш профессор имеет в виду это ??

while(*++argv !=NULL)

    printf("%s\n",*argv);
person Rozuur    schedule 25.02.2010