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]