Firstly, char **x
and char *x[]
are not equivalent, except as function parameter declarations.
Equivalent:
int main(int argc, char **argv);
int main(int argc, char *argv[]); // equivalent
Not equivalent:
{
char **pointer;
char *array[3];
}
A C T *
pointer can point to a single object of type T
, or it can point to any of the elements of an "array of T
", and can also point one element beyond the end of such an array.
This information isn't contained in the pointer's language-level, programmer-visible type information.
In some cases a compiler can deduce these situations and provide useful diagnosis if mistakes are made.
A compiler can trace the data flow of where an expression's value came from.
For instance, given:
char *array[3]; /* array of 3 "char *" pointers */
char **ptr = array; /* pointer to array[0] */
Here, the compiler can analyze that ptr
was initialized from array
. And so between that initialization and any other point in the program, if no assignment to ptr
takes place, it can be assumed to still be pointing to array[0]
.
So it is possible for the compiler to produce a warning for a dubious expression like ptr + 5
, while remaining silent for ptr + 3
.
ISO C doesn't require any such analysis or diagnostic, though; it's a "quality of implementation" matter.
There are limitations to how much can be diagnosed statically. C functions can receive pointer values as parameters "out of nowhere", about which nothing can be reasonably be known at compile time.
By the way, the declaration style char* ptr
is a bad habit; it should be styled as char *ptr
. Note that char* a, b
declares a
as a pointer and b
as char
. The syntax is that char
is a list of "declaration specifiers". These specifiers are followed by a comma-separated list of "declarators". These declarators are *a
and b
, respectively. If you write char* ptr
, you're putting a whitespace division in the middle of the declarator, while clumping it together with the specifier.
This is a bit like taking the arithmetic expression x + x*y + y
and writing it as x+x * y+y
, so it looks like multiplication is done last.
Avoid such misleading whitespace in programming.