The purpose of scandir
is to retrieve an array or 'list' of dirent
s.
While there are a few differences between 'pointer-to-first-array-element' and an actual array (which i highly recommend to read about if you intent to use c), we might consider them equal for this case.
As such an array of dirent
structures would be struct dirent *namelist
(which is not the case).
But the function actually yields an indirect-list, thus an array of pointers to dirent
structures: struct dirent **namelist
.
This is how namelist
is defined in the example and this also explains the access via namelist[n]->d_name
. Since namelist is an array -> namelist[n]
is an array-element (a pointer to dirent). The 'arrow operator' dereferences this pointer and accesses the field d_name
.
That was the easy part, now lets look at the function call.
The documentation you linked states
collected in array namelist which is allocated via malloc
This means that somewhere inside of scandir
malloc
is called and returns a pointer to the allocated memory. However the pointers value must somehow be known to the caller of scandir
. One possibility would be to simply return it just as malloc
does. But instead it was chosen to use an 'output-parameter'. This simply means a pointer to the variable (meaning its address) that would have received that value if it was a typical 'return-parameter'. This is where the third asterisk (*) comes from. As you know: the addressof-operator (&) just gives that address. This is why &namelist
is passed as 'output-argument'.
To maybe better understand output-parameters think of the scanf
function. Here also each value that you want to 'scan' is passed as output-parameter to the function. If you want to receive an integer you create an int
variable (e.g. int myVal;
) and pass it's address (scanf("%d", &myVal);
). The expected parameter type would be int *
.
Or again speaking generally:
<result-type> resultValue;
<return-type> returnValue = <function>(&resultValue);
where the function with output parameter would be defined as
<return-type> <function>(<result-type> *foo){...}
And yes, the addressof operator adds an asterisk (*) to the type (depending on the type this might be a bit more difficult then just adding the asterisk (e.g. function pointers or pointers to array (actual arrays))).
In our case <result-val>
is struct dirent **
and the third asterisk is added for the parameter type.
As a last note:
the returntype of scandir
is the number of elements in the array.
Since namelist
does not hold the length information of the array in its type, you need the return value to know how many values you can access.