Can static_cast turn a non-null pointer into a null pointer?

sharptooth picture sharptooth · Aug 12, 2010 · Viewed 8.7k times · Source

I need to write code for a callback function (it will be called from within ATL, but that's not really important):

HRESULT callback( void* myObjectVoid )
{
    if( myObjectVoid == 0 ) {
       return E_POINTER;
    }
    CMyClass* myObject = static_cast<CMyClass*>( myObjectVoid );
    return myObject->CallMethod();
}

here the void* is guaranteed to be a pointer to CMyClass, so static_cast is legal. My concern is the code must be as portable (to newer versions of Visual C++ at least) as possible. So to be super-paranoic I'm inclined to check the CMyClass* pointer as well - I mean what if it turns out to be null?

    if( myObjectVoid == 0 ) {
       return E_POINTER;
    }
    CMyClass* myObject = static_cast<CMyClass*>( myObjectVoid );
    if( myObject == 0 ) {
       return E_POINTER;
    }

Is the second check reasonable? Is it possible for static_cast to turn a non-null pointer into a null pointer?

Answer

Nordic Mainframe picture Nordic Mainframe · Aug 12, 2010

static_cast can change the pointer value, if you cast between object parts on different offsets:

class A{ int x; }; class B{ int y; };
class C : A,B {};

C *c=new C(); 

B *b=c; 
// The B part comes after the A part in C. Pointer adjusted

C *c2=static_cast<C*>(b); 
// Pointer gets adjusted back, points to the beginning of the C part

However, "The null pointer value (4.10) is converted to the null pointer value of the destination type." (5.2.9-8), i.e. if c is NULL, then b is also NULL (and not adjusted) and thus c2 is set to NULL. The whole thing means: if static casting a non-NULL myObjectVoid yields NULL, then the value of myObjectVoid was obtained by circumventing the type system somehow. And it means, that the compiler might throw your second check away because "it can't happen anyway".