The reason char **
-> const char**
is a “dangerous” conversion is the following code:
const char immutable[] = "don't modify this";
void get_immutable_str(const char **p) {
*p = immutable;
return;
}
int main() {
char *ptr;
get_immutable_str(&ptr); // <--- here is the dangerous conversion
ptr[0] = 0;
}
The above code attempts to modify a non-modifiable object (the global array of const char
), which is undefined behavior. There is no other candidate in this code for something to define as “bad”, so const-safety dictates that the pointer conversion is bad.
C does not forbid the conversion, but gcc
warns you that it’s bad. FYI, C++ does forbid the conversion, it has stricter const-safety than C.
I would have used a string literal for the example, except that string literals in C are “dangerous” to begin with — you’re not allowed to modify them but they have type array-of-char
rather than array-of-const char
. This is for historical reasons.
I thought a pointer to an address can always be casted to a const pointer
A pointer-to-non-const-T can be converted to a pointer-to-const-T. char **
-> const char**
isn’t an example of that pattern, because if T
is char *
then const T
is char * const
, not const char *
(at this point it’s probably worthwhile not writing the const
on the left any more: write char const *
and you won’t expect it to be the same as T const
where T is char *
).
You can safely convert char **
to char * const *
, and (for reasons that require a little more than just the simple rule) you can safely convert char **
to char const * const *
.