122

It seems that the argv[argc] is always NULL, so I think we can traverse the argument list without argc. A single while loop will do this.

If there is always a NULL at the end of argv, why do we need an argc?

Cole Tobin
  • 9,206
  • 15
  • 49
  • 74
StarPinkER
  • 14,081
  • 7
  • 55
  • 81

5 Answers5

110

Yes, argv[argc]==NULL is guaranteed. See C11 5.1.2.2.1 Program startup (my emphasis)

If they are declared, the parameters to the main function shall obey the following constraints:

The value of argc shall be nonnegative. argv[argc] shall be a null pointer.

Providing argc therefore isn't vital but is still useful. Amongst other things, it allows for quick checking that the correct number of arguments has been passed.

Edit: The question has been amended to include C++. n3337 draft 3.6.1 Main function says

2 ...argc shall be the number of arguments passed to the program from the environment in which the program is run. .... The value of argc shall be non-negative. The value of argv[argc] shall be 0.

simonc
  • 41,632
  • 12
  • 85
  • 103
  • 37
    And `argc` could be quite big, because the shell is doing expansion (so in `ls *` the `*` is expanded by the shell before `execve` of `/bin/ls` executable). On my system, I can have an `argc` of several hundred thousands. – Basile Starynkevitch Aug 31 '13 at 11:37
  • That's pretty cool, this never occurred to me since I always considered `argc` sufficient, but I can definitely think of situations where this guarantee would be relevant and even required. +1 – Thomas Aug 31 '13 at 16:13
  • 6
    @BasileStarynkevitch Time of merely stepping through an array of pointer values one extra time until NULL, to get the count, is miniscule compared to time already spent generating the pointer array, and even more irrelevant compared to actually using each argument value in the program. And if just checking if argument count is more than N, then going through entire array is not needed. Still, I fully agree, that `argc` was and is a good thing. – hyde Sep 01 '13 at 10:58
  • (**"Time ... to get the count is minuscule compared to ..."**: if only I had a dollar for each _"that particular redundant extra processing is irrelevant compared to X"_ comment... Even in a single biggish program if one diligently ignored every single tiny extra cruft someone declared "irrelevant", those would quickly add up to some real measurable bloat, I guess. Anyhow, if nothing else, it's also a matter of taste. _All things being (roughly) equal_ (i.e. costs allow), actually giving a shit wins, by itself, over being a little sloppy justified by not being even more sloppy... ;) ) – Sz. Jan 15 '22 at 01:24
44

Yes, argv[argc] is guaranteed to be a null pointer. argc is used for convenience.

Quoting the official explanation from C99 Rationale, note the words redundant check:

Rationale for International Standard — Programming Languages — C §5.1.2.2.1 Program startup

The specification of argc and argv as arguments to main recognizes extensive prior practice. argv[argc] is required to be a null pointer to provide a redundant check for the end of the list, also on the basis of common practice.

Community
  • 1
  • 1
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
19

It's for historical reasons, and compatibility with old code. Originally, there was not a guarantee that there would exist a null pointer as the last element of the argv array. But argc has always existed.

zentrunix
  • 2,098
  • 12
  • 20
  • 1
    ...Which is a shame, in a way. If we had `int main(char *argv[], int argc, ...)`, then some programs could just omit the `argc` because they do not need it. Opposite (needing `argc` but not `argv`) is probably never useful in a real program. – hyde Sep 04 '13 at 05:46
  • @hyde: see comment above by Basile Starynkevitch – zentrunix Sep 04 '13 at 11:39
6

We "need" it, because it's required by various standards.

We are free to ignore the value completely, but since it is first parameter of main, we must have it in parameter list. In C++ (and probably non-standard C dialects), you can just omit the parameter name, like this C++ snippet (easy to convert to 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;
}

In standard C, with common warnings settings, unused parameter generates warning, which can be fixed by a statement like (void)argc; which causes the name to be used without generating any code.

argc is nice to have, because otherwise many programs would need to walk thorugh the parameters to get the count. Also, in many programming languages with arrays that have length, there isn't any argc parameter, there's just an array with the items.

hyde
  • 60,639
  • 21
  • 115
  • 176
  • The question is about both C and C++. In C, the parameter name is required. –  Sep 01 '13 at 09:21
0
  • In the event one requires to access the last argument from a list of inputs it is more convenient to use argv[argc - 1] rather than looping.
  • It is better (cleaner) to have argc provided to me rather than having to write code that will give me the count separately when the logic requires me to (and there are cases where this can happen).
Aregawi
  • 41
  • 3