Why is argv (argument vector) in C defined as a pointer and what is the need for defining its zeroth as the program name?

安稳与你 提交于 2019-12-07 17:10:00

问题


#include <stdio.h>
int main(int argc, char *argv[])
{
 int i;
 for(i=1;i<argc;i++)
  printf("%s%s", argv[i], (i<argc-1)? " ":"");
 printf("\n");
 return 0;
} 

Given above is a simple C program that outputs command line inputs. Here argc is the argument counter. argv is said to be an array that contains arguments. My question is: why does it define as a pointer to a character array instead of a normal array? Also what is the need for defining its zeroth element (argv[0]) as the name by which the program is invoked.

I am a beginner and please explain it high level perspective.


回答1:


argv is defined as a pointer rather than as an array because there is no such thing as an array parameter in C.

You can define something that looks like an array parameter, but it's "adjusted" to array type at compile time; for example, these two declarations are exactly equivalent:

int foo(int param[]);
int foo(int param[42]); /* the 42 is quietly ignored */
int foo(int *param);    /* this is what the above two declarations really mean */

And the definition of main can be written either as:

int main(int argc, char *argv[]) { /* ... */ }

or as

int main(int argc, char **argv) { /* ... */ }

The two are exactly equivalent (and the second one, IMHO, more clearly expresses what's actually going on).

Array types are, in a sense, second-class types in C. Code that manipulates array almost always does so via pointers to the elements, performing pointer arithmetic to traverse the elements.

Section 6 of the comp.lang.c FAQ explains the often confusing relationship between arrays and pointers.

(And if you've been told that arrays are "really" pointers, they're not; arrays and pointers are distinct things.)

As for why argv[0] points to the program name, that's just because it's useful. Some programs print their names in error messages; others may change their behavior depending on the name by which they're invoked. Bundling the program name with the command-line arguments was a fairly arbitrary choice, but it's convenient and it works.




回答2:


The char *argv[] is a pointer that an array of char * has decayed into. For example, invoking a command like this:

$ ./command --option1 -opt2 input_file

could be viewed as:

char *argv[] = {
    "./command",
    "--option1",
    "-opt2",
    "input_file",
    NULL,
};
main(4, argv);

So basically there is an array of strings outside main, and it is passed to you in main:

    char *argv[]
    \- --/     ^
      V        |
      |   It was an array
      |
of strings

Regarding argv[0] being the invocation command, the reason is largely historical. I don't know what the first person who thought of it thought about, but I can tell at least one usefulness for it.

Imagine a program, such as vim or gawk. These programs may install symbolic links (such as vi or awk) which point to the same program. So effectively, running vim or vi (or similarly gawk or awk) could execute the exact same program. However, by inspecting argv[0], these programs can tell how they have been called and possibly adjust accordingly.

As far as I know, neither of the programs I mentioned above actually do this, but they could. For example vim called through a symbolic link named vi could turn on some compatibility. Or gawk called as awk could turn off some GNU extensions. In the modern world, if they wanted to do this, they would probably create scripts that gives the correct options, though.




回答3:


It is not defined as a normal array because in C the size of array elements has to be known at compile time. The size of char * is known, the size (length) of your arguments is not.

argv[0] contains the name of the invoked process because it is possible to invoke it by any arbitrary name. e.g. exec family of calls can specify what it wants and you are allowed to invoke a program via a symlink. argv[0] allows the program to offer different functionality depending on the invocation name.




回答4:


The questions you ask are really answered best by simply saying its all "by definition". i.e. a set of rules designed and agreed upon by a committee.

Here is what C11 says: (see emphasized sections)

5.1.2.2.1 Program startup
1 The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: int main(void) { /* ... */ } or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared): int main(int argc, char argv[]) { / ... */ } or equivalent;10) or in some other implementation-defined manner.
2 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.
— If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup.
The intent is to supply to the program information determined prior to program startup from elsewhere in the hosted environment. If the host environment is not capable of supplying strings with letters in both uppercase and lowercase, the implementation shall ensure that the strings are received in lowercase.
— If the value of argc is greater than zero, the string pointed to by argv[0] represents the program name; argv[0][0] shall be the null character if the program name is not available from the host environment. If the value of argc is greater than one, the strings pointed to by argv[1] through argv[argc-1] represent the program parameters.
— The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.



来源:https://stackoverflow.com/questions/21732633/why-is-argv-argument-vector-in-c-defined-as-a-pointer-and-what-is-the-need-for

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!