null pointer to member

The most straightforward implementation of a pointer to member is to store the offset:

struct Struct
{
    int a;
    int b;
};

The internal value of &Struct::a is 0 and &Struct::b is sizeof(int).

This leads to the illusion that &Struct::a, a valid pointer, is equal to a null pointer. Not only does this violate the standard, but also breaks many codes existing in practice.

The current (pre-0x) orthodox method of defining a cast from user-defined class to bool is not using operator bool (which leads to some unwanted consequences), but something like this:

class MyClass
{
   /* ....... */
   struct BooleanConvert { int val; };
   operator int BooleanConvert::* () const
   {
       return ( /* true */ ) ? &BooleanConvert::val : 0;
   }
};

It is hard to read, but the idea is simple: return a valid pointer (to member) if true, a null pointer (to member) if false.

Q: It seems both pointers evaluate to 0. How do they distinguish them?

A: In practice, a null pointer to member is represented, internally, by a value of -1 instead of 0!

So,

#include <cstdio>
#include <cstddef>
using namespace std;

struct Struct
{
    int a;
};

int main()
{
    union
    {
        int Struct::*ptr;
        void * val;
    };
    ptr = 0;
    printf ("%p\n", val);
}

the above program would output 0xffffffff (32-bit systems).

Fortunately, this does not annoy. We can safely ignore this detail (except when writing a compiler, of coz..) It seems that, except using unions or brutal memory access, there is no way to convert pointers to member to/from integers and normal pointers. (C-style casts, reinterpret_cast, etc. all reject such conversions.)


Related posts:

  1. NULL can be a valid address

Tags:

Leave a Reply

*

Hint: Register at Gravatar and your comments will be accompanied by your personalized icon.