int main(int carg, const char **varg) {

varg is a pointer to a second pointer. This second pointer points to a char. This char is ...

either: a single char (1st case)
or: a char that constitutes the first char of a char array. (2nd case)

Is this understanding correct?

The thing I don't understand is why you would want to pass a pointer to a pointer as an argument.

If you wanted to pass (by reference) a single char to the function, you could simply write:

int func(int carg, const char *v) {
//code ...
}

In the 2nd case, where you want to pass (by reference) a char array to the function, one could use the same function (where this time, v points to the first element of the array passed to the function):

int func(int carg, const char *v) {
//code ...
}

In summary, I don't understand why you would want to use a pointer to a pointer as argument to a function.

The concrete case I have is the following declaration of a main function:

int main(int carg, const char **varg);

**varg handles the arguments on the command line.
One can access the command line arguments using varg[1], varg[2], etc.
So, obviously, what **varg does is simply to save the command line arguments in an array. But this could be achieved in a more simple way with the following code:

To store a string you need an array of chars in memory. Pointer to any array in C is [type of array elements] * which is essentially pointer to first element in this array. In case of strings it is char *.

Arguments of command line is array of strings. That means, you have an array, where each element is cell in memory, containing pointer to another array - array of char. In this case type of elements in this array of pointers to array is char *, what give us proper type of pointer to this array (just substitute char * to formula above): char **.