char *(*ptr)[4]
is an array pointer to an array of pointers.
With less obfuscated syntax: if you have a plain array int arr[4];
then you can have an array pointer to such an array by declaring int (*arr_ptr)[4]
.
So there are arrays, regular pointers and array pointers. Things get confusing because when you use the array name by itself, arr
, it decays into a regular pointer to the first element. Similarly, if you have a regular pointer and let it point at the array, ptr = arr;
it actually just points at the first element of the array.
Array pointers on the other hand, points at the "whole array". If you take sizeof(*arr_ptr)
from the example above, you would get 4*sizeof(int)
, 4*4=16 bytes on a 32-bit machine.
It should be noted that an array pointer a mildly useful thing to have. If you are a beginner, you don't really need to waste your time trying to understand what this is. Array pointers are mainly there for language consistency reasons. The only real practical use for array pointers is pointer arithmetic on arrays-of-arrays, and dynamic allocation of multi-dimensional arrays.