Can static_cast turn a non-null pointer into a null pointer?
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*>( myObject开发者_开发问答Void );
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?
No. If the pointer refers to a valid object, and the conversion is valid, then the result will also refer to a valid object, so it won't be null. If either is invalid, then the code is incorrect and the result is undefined. So the only way for valid usage to give a null result is to start with null.
In the specific case of converting between object pointers and void pointers, the standard has this to say (5.2.9/10):
A value of type "pointer to object" converted to "pointer to
void
" and back to the original pointer type will have its original value.
and this (4.10/3)
The result of converting a "pointer to T" to a "pointer to
void
" points to the start of the storage location where the object of type T resides
so the original and final object pointers will be the same, and the void
pointer will be null if and only if the object pointers are.
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".
The only change static_cast
should make to a pointer is for word-alignment. So, in theory, of myObjectVoid
pointed to the last byte in memory, it's possible that it might be 'aligned-up" to 0, but I don't see that as a realistic concern.
No, the second check is not reasonable. It is not possible for static_cast
to turn a non-null pointer into a null pointer. The only thing static_cast
may change about the supplied value in your case (being a pointer) is to adjust the address. Otherwise it's strictly concerned with advising the rest of the compiler's type analysis that the result of the expression should be treated as the target type. For a pointer, that means that dereferencing finds the right address within the target object, and that increment and decrement strides are appropriate to the type's size.
精彩评论