argv declared as "a pointer to pointer to the first index of the array", rather than just being "a pointer to the first index of array" (
Why is the notion of "pointer to pointer" required here?
Argv is basically like this:
On the left is the argument itself--what's actually passed as an argument to main. That contains the address of an array of pointers. Each of those points to some place in memory containing the text of the corresponding argument that was passed on the command line. Then, at the end of that array there's guaranteed to be a null pointer.
Note that the actual storage for the individual arguments are at least potentially allocated separately from each other, so their addresses in memory might be arranged fairly randomly (but depending on how things happen to be written, they could also be in a single contiguous block of memory--you simply don't know and shouldn't care).
Because that's what the operating system provides :-)
Your question is a little bit of a chicken/egg inversion issue. The problem is not to choose what you want in C++, the problem is how you say in C++ what the OS is giving you.
Unix passes an array of "strings", each string being a command argument. In C/C++, a string is a "char*", so an array of strings is char* argv, or char** argv, according to taste.
First, as a parameter declaration,
char **argv is the same as
char *argv; they both imply a pointer to (an array or set of one or more possible) pointer(s) to strings.
Next, if you only have "pointer to char" — e.g. just
char * — then in order to access the nth item, you'll have to scan the first n-1 items to find the nth item's start. (And this would also impose the requirement that each of the strings are stored contiguously.)
With the array of pointers, you can directly index the nth item — so (while not strictly necessary — assuming the strings are contiguous) it is generally much more convenient.
./program hello world
argc = 3 argv --> "./program\0" argv --> "hello\0" argv --> "world\0"
It is possible that, in an os provided array of characters:
"./program\0hello\0world\0" argv ^ argv ^ argv ^
if argv were just a "pointer to char" you might see
"./program\0hello\0world\0" argv ^
However (though likely by design of the os) there is no real guarantee that the three strings "./program", "hello", and "world" are contiguous. Further, this kind of "single pointer to multiple contiguous strings" is a more unusual data type construct (for C), especially compared with array of pointers to string.
Why C/C++ main argv is declared as “char* argv”
A possible answer is because the C11 standard n1570 (in §184.108.40.206.1 Program startup) and the C++11 standard n3337 (in §3.6.1 main function) require that for hosted environments (but notice that the C standard mentions also §220.127.116.11 freestanding environments) See also this.
The next question is why did the C and C++ standards choose
main to have such a
int main(int argc, char**argv) signature? The explanation is largely historical: C was invented with Unix, which has a shell which does globbing before doing
fork (which is a system call to create a process) and
execve (which is the system call to execute a program), and that
execve transmits an array of string program arguments and is related to the
main of the executed program. Read more about the Unix philosophy and about ABIs.
And C++ tried hard to follow the conventions of C and be compatible with it. It could not define
main to be incompatible with C traditions.
If you designed an operating system from scratch (still having a command line interface) and a programming language for it from scratch, you'll be free to invent different program starting conventions. And other programming languages (e.g. Common Lisp or Ocaml or Go) have different program starting conventions.
main is invoked by some crt0 code. Notice that on Windows the globbing may be done by each program in the equivalent of crt0, and some Windows programs can start thru the non-standard WinMain entry point. On Unix, globbing is done by the shell (and
crt0 is adapting the ABI, and the initial call stack layout that it has specified, to calling conventions of your C implementation).
Rather than thinking of it as "pointer to pointer", it helps to think of it as "array of strings", with
 denoting array and
char* denoting string. When you run a program, you can pass it one or more command-line arguments and these are reflected in the arguments to
argc is the count of arguments and
argv lets you access individual arguments.
In many cases the answer is "because it's a standard". To quote C99 standard:
— If the value of argc is greater than zero, the array members argv through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup.
Of course, before it has been standardized it was already in use by K&R C in early Unix implementations, with the purpose of storing command-line parameters (something you have to care in Unix shell such as
/bin/sh but not in embedded systems). To quote first edition of K&R's "The C Programming Language" (pg. 110):
The first (conventionally called argc) is the number of command-line arguments the program was invoked with; the second (argv) is a pointer to an array of character strings that contain the arguments, one per string.