Pointers-to-members
Mark Mitchell
mark at codesourcery.com
Wed Feb 23 00:03:13 UTC 2000
> Yes. I apologize for my own idiocy.
^^^^^^
Another typo, I guess :-)
No, that's the right spelling. :-) Check www.dictionary.com. I might
be an idiot, but at least I can spell! :-)
Ach, but, what is the value for the NULL pointer to data member? I guess -1
would do, unless there are cases I can't think of where the pointer to member
would legitimately have a negative value. Maybe 0x8000000000000000
is better...
I'm a step ahead of you. :-) I already started a thread on precisely
this. Here's some more analysis:
o All pointer-to-member offsets start out non-negative.
o Only casts which would increase the `this' pointer could cause
the pointer-to-member to go negative.
o A reinterpret_cast leaves the value unspecified, except that:
- NULL is converted to NULL
- If you convert back, you're OK.
But, therefore, converting a non-NULL value to NULL is explicitly
permitted by the standard.
o A pointer-to-base can be converted to a pointer-to-derived via
an implicit conversion/static_cast.
It's illegal to do this if the base is virtual. But, that's the
only case in which the `this' pointer can increase.
o A pointer-to-derived can be converted to a pointer-to-base. This
will normally increase the `this' pointer. The standard is a
little unclear here, but I think it wants to say that this is
illegal precisely in the cases where the offset would go negative:
[expr.static.cast]
If class B contains the original member, or is a base or derived
class of the class containing the original member, the resulting
pointer to member points to the original member. Otherwise, the
result of the cast is undefined.
Consider this program:
struct S
{
char c;
};
struct U
{
char d;
};
struct T : public U, public S
{
};
typedef char S::*sp;
typedef char T::*tp;
int main ()
{
sp s;
tp t;
t = &T::d;
s = static_cast<sp> (t);
if (s == 0)
return 1;
}
With GCC, this program wil return 1, i.e., the `&T::d' pointer has
become NULL when converted to `char S::*'. But, I think this
behavior is OK: `S' does not contain the original member `U::d'.
So, adding `1' to the offset (and using `0' for NULL) is OK; so is
using `-1' for NULL, and using the offset for the pointer-to-member
itself.
--
Mark Mitchell mark at codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
More information about the cxx-abi-dev
mailing list