static_cast可以将非空指针转换为空指针吗?

sha*_*oth 6 c++ pointers static-cast visual-c++

我需要为回调函数编写代码(它将在ATL中调用,但这并不重要):

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

这里void*保证是指针CMyClass,所以static_cast是合法的.我担心的是代码必须尽可能是可移植的(至少对于较新版本的Visual C++).因此,为了超级偏执,我倾向于检查CMyClass*指针 - 我的意思是如果它被证明是空的?

    if( myObjectVoid == 0 ) {
       return E_POINTER;
    }
    CMyClass* myObject = static_cast<CMyClass*>( myObjectVoid );
    if( myObject == 0 ) {
       return E_POINTER;
    }
Run Code Online (Sandbox Code Playgroud)

第二次检查合理吗?是否可以static_cast将非空指针转换为空指针?

Nor*_*ame 7

如果在不同偏移量的对象部分之间进行转换,static_cast可以更改指针值:

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
Run Code Online (Sandbox Code Playgroud)

但是,"空指针值(4.10)将转换为目标类型的空指针值." (5.2.9-8),即如果 cNULL,那么b也是NULL(并且没有调整)因此c2被设置为NULL.整个事情意味着:如果静态转换非NULL myObjectVoid产生NULL,则myObjectVoid通过以某种方式绕过类型系统获得值.这意味着,编译器可能会抛弃你的第二张支票,因为"它无论如何都不会发生".


Mik*_*our 6

否.如果指针引用了有效对象,并且转换有效,则结果也将引用有效对象,因此它不会为空.如果其中一个无效,则代码不正确,结果未定义.因此,有效使用给出null结果的唯一方法是从null开始.

在对象指针和void指针之间进行转换的特定情况下,标准就是这样说的(5.2.9/10):

转换为"指向"指针void并返回原始指针类型的"指向对象的指针"类型的值将具有其原始值.

这个(4.10/3)

将"指针指向T"转换为"指向指针"的结果指向T void类对象所在的存储位置的开头

所以原始和最终的对象指针将是相同的,void当且仅当对象指针是指针时,指针才为空.