In this context, the type char**
is a pointer to a pointer to an array of char
s. (It can also mean a pointer to a pointer to a single char
, but that's not how it's used with _dupenv_s()
).
The _dupenv_s()
function allocates an array of char
s by asking the operating system to reserve some chunk of memory big enough to hold it. The operating system reserves a chunk of memory and gives the _dupenv_s()
function the address of this newly-allocated char
array. The _dupenv_s()
function stores the address of this array into a char*
variable, because it's a pointer to an array of char
s.
Now, the function has to pass this char*
value out to the caller so the calling code can use it. The return value is already used to return an error code, so that can't be used. But let's say that the caller has a char*
variable ready to receive the address to the allocated buffer.
If the _dupenv_s()
function knows where the caller's char*
variable is located, then the function can go ahead and fill the caller's char*
variable with the correct value. To do that, the caller needs to pass the address of the caller's char*
variable. That is, you need to pass a pointer to a pointer to an array of chars
. That means a char**
must be passed.
Note that's also the reason why sizeInBytes
is a size_t*
. The caller has a variable size_t
, and the caller can pass the address of the variable to the function as a size_t*
so that the function can fill the variable with the correct value.
While it may be true that strlen(buffer) == sizeInBytes
, the strlen()
function determines the length of the string by counting the number of characters until it sees a null-terminator. The amount of time required for strlen()
to complete is linear to the number of characters, i.e. it's not constant. Why not skip the trouble of requiring the caller to do that and just provide the size directly?
If pointers still confuse you (and they are confusing at times), this Stack Overflow answer can be of assistance.