pete said:
Michael said:
There is special wording that allows any object,
including an array of arrays,
to be accessed completely using pointers to unsigned char.
This is what makes memcpy() usable.
However, for any other type this is an issue.
If it was
int a[2][2] = {{1, 2}, {3, 4}}, *b = (int *)a;
^^^^^^^
instead,
there wouldn't be a problem accessing b[3], would there?
There would. The same arguments hold.
No, the same arguments don't hold.
Actually, yes, they do. Observe - fit the first:
int a[2][2] = {{1, 2}, {3, 4}},
You now have an array of two arrays of int.
You get the address of the first of these int arrays, convert it to an
int pointer, and assign it to b.
printf("%d\n", *(b + 3));
You invoke undefined behaviour by increasing _that int pointer_ beyond
its legal boundary.
Fit the second:
int a[2][2] = {{1, 2}, {3, 4}},
You now have an array of two arrays of int.
You get the address of the entire array, convert it to an int pointer,
and assign it to b.
printf("%d\n", *(b + 3));
You invoke undefined behaviour by increasing _that int pointer_ beyond
its legal boundary.
Note that:
- the address of an array and the address of its first member are
identical.
- the entire array is properly aligned for ints, so a conversion of its
base address (or the address of its first member, which is the same
except for type) to int * must succeed and give the address of the
first int in the array.
- once a pointer has been converted to another pointer type, there is
nothing in the Standard that allows you to deduce the original type.
IOW, if you have
int a[2][2] = {{1, 2}, {3, 4}}, *b = (int *)a, *c = a[0];
then b==c _must_ evaluate to 1. The two pointers you get from those two
conversions have exactly the same value, and exactly the same
requirements.
Note that this is _not_ true of a and a[0]; but this is because a has a
different type than a[0]. Once you convert them both to int *, this
distinction is, obviously, lost.
Richard