The problem is, when we do &array
, we are getting a char (*)[10]
from an char [10]
, instead of a char **
.
Before we do our experiment, I will emphasize that, when we pass an array as an argument to a function, C actually casts the array to a pointer. The big bucket of data is not copied.
Thus, int main(int argc, char **argv)
is identical to int main(int argc, char *argv[])
in C.
This made it available for us to print the address of an array with a simple printf
.
Let's do the experiment:
char array[] = "john";
printf("array: %p\n", array);
printf("&array: %p\n", &array);
// Output:
array: 0x7fff924eaae0
&array: 0x7fff924eaae0
After knowing this, let's dig into your code:
char array[10] = "john";
char *bla = array;
check(&bla);
check(&array);
bla
is char *
, and &bla
is char **
.
However, array
is char [10]
, and &array
is char (*)[10]
instead of char **
.
So when you pass &array
as an argument, char (*)[10]
acts like a char *
when passing as an argument, as is said above.
Therefore **(char **) &bla == 'j'
while *(char *) &array == 'j'
. Do some simple experiments and you will prove it.
And you are casting void *elemAddr
to a char **
and try to deference it. This will only work with &bla
since it is char **
. &array
will cause a segfault because "john" is interpreted as an address as you do the cast.