【问题标题】:Can static_cast turn a non-null pointer into a null pointer?static_cast 可以将非空指针变成空指针吗?
【发布时间】:2010-08-12 14:49:07
【问题描述】:

我需要为回调函数编写代码(它将在 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能不能把非空指针变成空指针?

【问题讨论】:

  • 为什么不只是无条件地转换,并在转换后检查 null ? static_cast 不会取消引用指针。
  • @Logan Capaldo:尽早检查感觉更好。

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


【解决方案1】:

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(并且未调整),因此设置了 c2NULL。整个事情的意思是:如果静态转换非NULL myObjectVoid 产生NULL,那么myObjectVoid 的值是通过某种方式绕过类型系统获得的。这意味着,编译器可能会抛出您的第二次检查是因为“无论如何都不会发生”。

【讨论】:

    【解决方案2】:

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

    在对象指针和空指针之间转换的具体情况下,标准有这样的说法(5.2.9/10):

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

    还有这个 (4.10/3)

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

    所以原始对象指针和最终对象指针相同,当且仅当对象指针相同时,void 指针才会为空。

    【讨论】:

      【解决方案3】:

      static_cast 应该对指针进行的唯一更改是字对齐。因此,理论上,myObjectVoid 指向内存中的最后一个字节,它可能会“对齐”为 0,但我不认为这是一个现实的问题。

      【讨论】:

      • 如果这是可能的,那不是一个大问题吗?我一直认为 0 是唯一一个有效指针不能具有的值。
      • 真正的问题是地址是向上还是向下舍入,还是由实现定义?
      【解决方案4】:

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

      【讨论】:

      • 好了。在非现实世界的场景中,传入一个精心设计的指向 static_cast 的指针可能会导致它被调整为使其为 NULL 的偏移量。当然,这在现实生活中永远不会发生。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-05
      • 2014-12-04
      • 1970-01-01
      • 2013-01-09
      • 2017-11-30
      • 2012-10-24
      • 2018-01-26
      相关资源
      最近更新 更多