On Wed, 16 Dec 2009 17:50:42 +0000 (UTC), Alok Singhal
Thanks. This is what I was looking for. I should have read the
standard more carefully as well. So 6.3.2.3p7 (N1336) applies here:
A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type. If the resulting
pointer is not correctly aligned for the pointed-to type, the behavior
is undefined. Otherwise, when converted back again, the result shall
compare equal to the original pointer.
There is no guarantee that int (*)[5] is correctly aligned for int *,
and even if it is, the standard makes no guarantees about dereferencing
such a pointer.
Do you just invent these assumptions or do you read them somewhere that
we can tell others to avoid?
Please bear with me while I try to explain myself. Isn't there a
difference between:
int array[5] = {2};
int (*ptr)[5] = &array;
and:
int array[20] = {2};
int (*ptr)[5] = (int (*)[5])(array + 6);
In the second snippet, "array + 6" is of type "pointer to int". In the
first snippet, "&array" is of type "int (*)[5]". So, if I understand
correctly, and I think that is what you're saying too: the first snippet
is well-defined by the standard, while the result second snippet, in
particular the assignment to "ptr" is implementation-defined.
So, *if I understand correctly*, in the second snippet above:
- the cast is needed because it coerces "a+6" to the correct type for
"ptr".
- if "ptr" is a pointer to (signed or unsigned) char, or any other type
that is correctly aligned for the type of "a+6" (int *), the
initialization is well-defined in that I can convert "ptr" back to
int * and get the same value.
- if "ptr" isn't correctly aligned for int *, the result of the
initialization is implementation-defined.