Assume that
int array[16];
There is standard conversion called array-to-pointer conversion, so array would be converted implic
The type of &array is int (*)[16] (a pointer to an array of 16 integers). The type of array, when left to decay, is int* (a pointer to an integer). They both point to the same location, but have a different meaning to the compiler.
If you do (&array)[0], the value you end up with is the original array of 16 integers, that you can subscript again, like (&array)[0][0]. (&array)[1] would be the next array of 16 integers, if there was one.
If you do array[0], the value you end up with is an integer, which you can't subscript again. array[1] is just the next integer. (This is true regardless of if array is a int[16] or a int*.)
Obviously, if you then turn your pointers into void pointers, you lose any semantic difference there could have been.