This is an example of how pointers and arrays are not equivalent in C. In particular: a rule that masses the decay of pointers is not applied recursively
This means that an array can be used as a pointer, but a pointer to an array cannot be used as a pointer to a pointer . This is what you experience here. This is why the compiler complains about inconsistent types when you do not explicitly push & str to char **. This should be your first clue that something is wrong.
The reason it calls segfault is this: the way the array automatically breaks into a pointer turns into the address of its first element. A pointer to an array is also a pointer to the address of the first element of the array. Thus, a pointer to an array and a pointer array are one and the same. In other words, str, when passed as a pointer, has a value identical to the string str. Therefore, if you try to make & str a pointer to a pointer, this will not work, since it is just a single-level pointer.
For instance,
void f(char** pp); void g(char* p); char[] str = "abcd"; // Lets say this is allocated at address 0x1234 g(str); // Value of p in g is 0x1234 (by automatic conversion of char[4] to char*) char* p_str = &str; // Value of p_str is 0x1234 g(p_str); // Value of p in g is again 0x1234 f(str); // Illegal, no conversion of char[] to char** (obvious) f(p_str); // Illegal, no conversion of char* to char** (obvious) f(&str); // Illegal, no conversion of char*[4] to char** (less obvious) f((char**)p_str); // Ok, now you're overriding the typecheck
But after the last call to f((char**)p_str) value of pp in f will still be 0x1234, because you did not change the value of p_str, you only suppressed the complaint about type checking. This means that * pp will be "a", not a pointer to an address containing "a". And that is why you get segfault when f tries to execute ** pp.
source share