C
Chris Torek
char a[2][2]
(void*)(a[0]) points to the first of two bytes.
(void*)(a) points to the first of four bytes.
Right.
Here is a useful (I think) way to think about the issues involved.
Imagine that pointers are not even fixed size (or, equivalently,
are fixed size but a megabyte each so that there is plenty of room
for the extra decoration I am about to describe).
Each pointer carries with it not only the "address of first byte
or word or whatever of object" but also "type of target object",
array dimensions if applicable, and/or offset within array if the
implementation feels like carrying such information.
Thus, some pointer value stored in some object p might contain the
actual literal (ASCII or EBCDIC or whatever) string:
"This pointer points to the third element of the array named
xyz in function glork() in stack frame #37. The array has type
`array 5 of pointer to array 2 of array 3 of pointer to function
(readonly pointer to char) returning void'."
(This is why "sizeof p" is one megabyte: that gives lots of room for
ASCII text.
In this implementation, comparisions for pointer equality first
simply (or complex-ly) checks whether they point to the same object
("array named <name>", "object named <name>", "malloc instance
#<number>"), and if the object is an array, have the same
element-number. If the types do not match, the comparison falls
back to locating the byte(s) to which the pointer points and seeing
if those are the same.
Dereferences (*p) first check whether the pointer points to an
actual, valid object, and if it is an array, whether the array offset
is within bounds, and so on.
Note that this implementation is able to reject attempts to use
a[0][3], even though the byte that would be addressed there exists.
By doing:
unsigned char *ucp = &a[0];
the implementation *does* allow accessing ucp[3], because the rules
for using a pointer of type "unsigned char *" that points into an
object explicitly allow accessing all the bytes of the object.
Converting the pointer back to "char (*)[2][2]", however, restores
the "correct" type, to which the subscript-limiting rules apply.