【问题标题】:static_cast void* char* vs static_cast void** char**static_cast void* char* 与 static_cast void** char**
【发布时间】:2013-04-29 14:10:20
【问题描述】:

如果我执行以下操作就可以了:

char* cp = "abc";
void* vp = NULL;
vp = static_cast<void*>(cp);//ok
cp = static_cast<char*>(vp);//ok

但以下不是:

char** cpp = &cp;
void** vpp = NULL;
vpp = static_cast<void**>(cpp);//error C2440: 'static_cast':
                               //cannot convert from 'char **' to 'void **'
cpp = static_cast<char**>(vpp);//error C2440: 'static_cast':
                               //cannot convert from 'void **' to 'char **'

请有人向我解释为什么不允许第二个示例。请不要引用 C++ 标准作为您的全部答案,因为我已经看到引用它的答案,但我不明白它们的意思。我想了解为什么第二个例子不起作用(即,如果你能举一个危险的例子,那将是一个很大的帮助)。因为我不明白。对我来说,这两个例子都是投射指针。为什么额外的间接级别会产生任何影响?

【问题讨论】:

  • 您可以将任何指针隐式转换为void *,并反向静态转换。但是对于T*U* 来说,情况并非如此,它们是不相关的。 (现在想想T = char*U = void*。)
  • 您可以将char** 转换为void*,反之亦然。
  • @Kerrek SB - 是的,但为什么不允许这样做?什么时候会不安全?

标签: c++ casting static-cast


【解决方案1】:

void * 指针可以指向“任何东西”,将所有指针转换为void * 有效,将所有指针从void * 转换为其他类型有效。

但是,void ** 是指向 void * 值的指针。而char ** 是一个指向char * 值的指针。这些类型并不指向可以相互转换的类型。如果你需要这样做,你可以使用void **vpp = reinterpret_cast&lt;void **&gt;(cpp);,但它“不安全”(你基本上是在告诉编译器“看,我知道我在这里做什么,所以就去做吧”,这可能不行你实际期望的...)

【讨论】:

  • 对不起,我还是不明白。如果某个字符串的地址为 0x12345678,我可以将它放在我的 char* 或 void* 中。如果我的 char* 的地址是 0x87654321,为什么我不能把那个值(地址 0x87654321)放在我的 void** 中? IE。为什么可以将 static_cast 0x12345678 转换为 void*,但不能将 static_cast 0x87654321 转换为 void**?什么时候/为什么会不安全?
  • @e244:问题是如果允许转换,您可以轻松(并且无需任何显式转换)颠覆类型系统。我提供了更长的解释作为答案,但简短的描述是双指针允许您以不安全的方式更改数据。
  • void* 可以指向一个函数吗(即函数指针是否可以转换为void*)?
  • @rubenvb:标准不保证,问题是在某些平台上,代码和数据的地址空间可能大小不同
【解决方案2】:

限制是为了避免破坏类型系统。第一次转换没问题:

type *p = ...;
void *vp = p;

当您放弃类型时,您不能对原始值造成过多的损害,因为void 对象几乎没有什么可做的,对vp 的所有更改都是本地指针,不会影响p

如果允许第二种情况:

type **p = ...;
void **vp = p;

那么完美且正确的代码可能会破坏您的应用程序。例如:

int *parray[10];
int **p = parray;
void **vp = p;
*vp = new double();  // now parray[0] is a pointer to a double object, 
                     // not a pointer to an int!!!

类型系统被颠覆了。

也就是说,问题在于,在第二种情况下,存在可以应用于目标指针的操作,这些操作可以修改原始对象并导致错误。类似的例子可以在const 其他情况下找到(您可以将int* 转换为const int*,但您不能将int** 转换为const int**...)。

【讨论】:

    猜你喜欢
    • 2011-10-31
    • 2014-05-29
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多