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

时间:2010-08-12 14:49:08

标签: c++ visual-c++ pointers static-cast

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

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

此处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;
    }

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

4 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:6)

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

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

  

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

和这(4.10 / 3)

  

将“指向T的指针”转换为“指向void的指针”的结果指向T类型的对象所在的存储位置的起点

所以原始和最终的对象指针将是相同的,当且仅当对象指针是。{/ p>时,void指针将为null。

答案 2 :(得分:0)

指针的唯一变化是static_cast用于字对齐。因此,从理论上讲,myObjectVoid指向内存中的最后一个字节,它可能与0“对齐”,但我不认为这是一个现实的问题。

答案 3 :(得分:0)

不,第二次检查不合理。 static_cast无法将非空指针转换为空指针。关于您提供的值(作为指针),static_cast唯一可能改变的是调整地址。否则,它严格关注建议编译器的其余类型分析,表达式的结果应该被视为目标类型。对于指针,这意味着解除引用会在目标对象中找到正确的地址,并且增量和减量步幅适合于类型的大小。