[snipped convoluted conversion rules
summary: pointers get "shifted" during conversion by an arbitrary
"conversion number"; except (char*). ]
You must be on the design team for the DeathStation 9900
(the C99 successor to the C90-based DeathStation 9000). ;-)
Natural generalization would be to associate a permutation with each
conversion - but for simplicity let's stay with conversion numbers.
The above is not such a strange idea as it might look like. Conversion
is an operation which may change a value. It is very natural in C++,
where conversions between pointers to base and derived class (in
sense of static_cast or dynamic_cast; implicit conversions behave
this way) must adjust the value of the pointer. I'm pretty sure
that in C conversions between pointers should behave like in
reinterpret_cast, however I'd like to see it decreed somehow.
I think this scheme might run afoul of the rules involving
pointers to structs and unions and to their elements. For
example,
Oh yes, thanks, I forgot about unions and structs. Well, not everything
is lost yet!
# 6.7.2.1 Structure and union specifiers
#
# 13 Within a structure object, the non-bit-field members and the units
# in which bit-fields reside have addresses that increase in the
# order in which they are declared. A pointer to a structure object,
# suitably converted, points to its initial member (or if that member
# is a bit-field, then to the unit in which it resides), and vice
# versa. There may be unnamed padding within a structure object,
# but not at its beginning.
#
# 14 The size of a union is sufficient to contain the largest of its
# members. The value of at most one of the members can be stored in
# a union object at any time. A pointer to a union object, suitably
# converted, points to each of its members (or if a member is a bit-
# field, then to the unit in which it resides), and vice versa.
The first doubt I have here is what "suitably converted" means. Is it
a direct conversion to pointer to type of its first member(s), or a
chain of conversions, or cast to (char*)? Let's give the Standard
a favour and assume the first possibility (direct cast), which seems
to be the worst case for us.
So, to the rules I layed out above let's throw in this one:
With conversions involving type pointer to struct or union the associated
number is 0 (zero), except when the second type is (void*).
Example:
(struct A*)->(int*) 0 (int*)->(struct A*) 0
(struct A*)->(void*) 7 (void*)->(struct A*) -7
(struct B*)->(void*) -22 (void*)->(struct A*) 22
I don't think we need to handle pointers to array in a special way.
And _Complex types shouldn't be a problem either. If they were,
we could add something there too, but I refuse to believe that the
whole pointer system would rely on this type.
union { long l; char c; } u;
long *lp = &u.l;
char *cp = &u.c;
assert ((void*)lp == (void*)cp);
No, the Standard demands these (taking the direct cast to be "suitably
converted"):
assert ((long*)&u == &u.l);
assert ( &u == (union*)&u.l);
assert ((char*)&u == &u.c);
assert ( &u == (union*)&u.c);
(void*)&u == &u.l; //no guarantee, might evaluate to 0
looks like it would run into trouble with the "conversion
numbers" mentioned above.
I believe it's repared now.