Навіщо нам потрібен аргумент, коли в кінці аргументу завжди є нуль?


117

Здається, що argv[argc]це завжди NULL, тому я думаю, що ми можемо пройти аргумент без аргументів argc. Один whileцикл зробить це.

Якщо NULLв кінці завжди є argv, навіщо нам це потрібно argc?


17
Це, мабуть, питання зручності. Надає програмісту простий спосіб позбавитись достроково, якщо аргументів не вистачає, без циклу. Інакше у нас, безумовно, були б функції, які називаються int argc(char *argv[])саме так :-))
cnicutar

5
Просто, щоб бути зрозумілим, "\0"це не те саме, що вказівник NULL ( 0еквівалентний NULL в C ++)
Mats Petersson,

31
Навіщо нам аргумент [argc], щоб бути NULL, якщо у нас є argc?
Ambroz Bizjak

7
Як ще ви визначили кількість аргументів за постійний час?
авакар

4
Не вважайте, що теги linux / unix тут доречні, оскільки така поведінка має бути справедливою для всіх компіляторів у всіх операційних системах.
Даррель Гофман

Відповіді:


106

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

Якщо вони оголошені, параметри основної функції повинні дотримуватися таких обмежень:

Значення argc не має негативного значення. argv [argc] - це нульовий покажчик.

argcТаким чином, надання не є життєво важливим, але все ж корисно. Крім усього іншого, це дозволяє швидко перевірити, чи було передано правильну кількість аргументів.

Редагувати: Питання було внесено до змін C ++. n3337 чернетка 3.6.1 Основна функція говорить

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


36
І argcможе бути досить великою, тому що оболонка робить розширення (так в розширюється за рахунок оболонки , перш ніж в виконуваний файл). У моїй системі я можу мати кілька сотень тисяч. ls **execve/bin/lsargc
Базиль Старинкевич

Це дуже круто, мені це ніколи не приходило в голову, оскільки я завжди вважав argcдостатньою, але я точно можу придумати ситуації, коли ця гарантія була б актуальною і навіть потрібною. +1
Томас

6
@BasileStarynkevitch Час просто переходити через масив значень вказівника один додатковий час, поки NULL, щоб отримати підрахунок, є мізерним порівняно з часом, витраченим на генерування масиву вказівника, і ще більше не має значення в порівнянні з фактично використанням кожного значення аргументу в програмі. І якщо просто перевірити, чи кількість аргументів більше N, то не потрібно проходити весь масив. Все-таки я повністю згоден, це argcбуло і є хорошою справою.
hyde

43

Так, argv[argc]гарантовано буде нульовим покажчиком. argcвикористовується для зручності.

Цитуючи офіційне пояснення C99 Rationale, зверніть увагу на слова надмірної перевірки :

Обґрунтування міжнародного стандарту - Мови програмування - C §5.1.2.2.1 Запуск програми

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


19

Це з історичних причин та сумісності зі старим кодом. Спочатку не було гарантії існування нульового вказівника як останнього елемента масиву argv. Але аргc завжди існував.


... Що певно, певним чином. Якби у нас були int main(char *argv[], int argc, ...), то деякі програми могли просто опустити те, argcщо їм це не потрібно. Навпаки (потребують, argcале ні argv), мабуть, ніколи не корисні в реальній програмі.
Гайд

@hyde: див. коментар вище від Basile
Starynkevitch

6

Нам це "потрібно", тому що цього вимагають різні стандарти.

Ми можемо повністю ігнорувати значення, але оскільки це перший параметр main, ми повинні мати його у списку параметрів. У C ++ (і, мабуть, нестандартних діалектах C) ви можете просто опустити ім'я параметра, як цей фрагмент 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параметра, є лише масив з елементами.


Питання стосується як C, так і C ++. В C потрібна назва параметра.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.