Зачем нам нужен argc, хотя в конце argv всегда есть нуль?

Кажется, что argv[argc] всегда NULL, поэтому я думаю, что мы можем пересечь список аргументов без argc. Один цикл while сделает это.

Если в конце argv всегда есть NULL, зачем нам нужен argc?

Ответ 1

Да, argv[argc]==NULL гарантируется. См. C11 5.1.2.2.1 Запуск программы (мой акцент)

Если они объявлены, параметры главной функции должны подчиняться следующие ограничения:

Значение argc должно быть неотрицательным. argv [argc] должен быть нулевым указатель.

Предоставление argc поэтому не является жизненно важным, но по-прежнему полезно. Помимо всего прочего, это позволяет быстро проверить правильность количества аргументов.

Изменить: вопрос был изменен, чтобы включить С++. n3337 черновик 3.6.1 Основная функция говорит

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

Ответ 2

Да, argv[argc] гарантированно является нулевым указателем. argc используется для удобства.

Цитируя официальное объяснение из Обоснования C99, обратите внимание на слова избыточная проверка:

Обоснование для международного стандарта - Языки программирования - C §5.1.2.2.1 Запуск программы

Спецификация argc и argv в качестве аргументов main распознает обширную предыдущую практику. argv[argc] требуется, чтобы он был нулевым указателем, чтобы обеспечить избыточную проверку для конца списка, также на основе обычной практики.

Ответ 3

Это по историческим причинам и совместимость со старым кодом. Первоначально не было гарантии, что в качестве последнего элемента массива argv будет существовать нулевой указатель. Но argc всегда существовал.

Ответ 4

Мы "нуждаемся" в нем, потому что это требуется по различным стандартам.

Мы можем полностью игнорировать это значение, но поскольку это первый параметр main, мы должны иметь его в списке параметров. В С++ (и, возможно, нестандартных диалектах C) вы можете просто опустить имя параметра, как этот фрагмент С++ (легко конвертировать в C):

#include <stdio.h> // C-compatible include, guarantees puts in global namespace

// program will print contents of argv, one item per line, starting from argv[0]

int main(int /*argc*/, char *argv[]) { // uncomment argc for C

    //(void)argc; // uncomment statement for C

    for (int i=0; argv[i]; ++i) {
        puts(argv[i]);
    }

    return 0;
}

В стандарте C, с общими предупреждениями, неиспользуемый параметр генерирует предупреждение, которое может быть исправлено с помощью инструкции типа (void)argc;, которая заставляет использовать имя без генерации какого-либо кода.

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