The argv
array is an array of strings (where each entry in the array is of type char*
). Each of those char*
arrays is, itself, NUL-terminated. The argv
array, itself, does not need to end in NULL (which is why a separate argc
variable is used to track the length of the argv
array).
In terms of those arrays being constructed to begin with, this is dependent on the calling program. Typically, the calling program is a shell program (such as BASH), where arguments are separated via whitespace (with various quoting options available to allow arguments to include whitespace). Regardless of how the argc
, argv
parameters are constructed, the operating system provides routines for executing a program with this as the program inputs (e.g. on UNIX, that method is one of the various variations of exec
, often paired with a call to fork
).
To make this a bit more concrete, suppose you ran:
./myprog "arg"
Here is an example of how this might look in memory (using completely fake addresses):
Addresss | Value | Comment
========================
0058 | 2 | argc
0060 | 02100 | argv (value is the memory address of "argv[0]")
...
02100 | 02116 | argv[0] (value is the memory address of "argv[0][0]")
02104 | 02300 | argv[1] (value is the memory address of "argv[1][0]")
...
02116 | '.' | argv[0][0]
02117 | '/' | argv[0][1]
02118 | 'm' | argv[0][2]
02119 | 'y' | argv[0][3]
02120 | 'p' | argv[0][4]
02121 | 'r' | argv[0][5]
02122 | 'o' | argv[0][6]
02123 | 'g' | argv[0][7]
02124 | '\0' | argv[0][8]
...
02300 | 'a' | argv[1][0]
02301 | 'r' | argv[1][1]
02302 | 'g' | argv[1][2]
02303 | '\0' | argv[1][3]