C++ 正在将指针转换为指针。。。指向指针?
我找到了这个片段C++ 正在将指针转换为指针。。。指向指针?,c++,pointers,casting,C++,Pointers,Casting,我找到了这个片段 void* operator new(size_t nbytes) { if (nbytes == 0) nbytes = 1; // so all alloc's get a distinct address void* ans = malloc(nbytes + 4); // overallocate by 4 bytes *(Pool**)ans = NULL; // use NULL i
void* operator new(size_t nbytes)
{
if (nbytes == 0)
nbytes = 1; // so all alloc's get a distinct address
void* ans = malloc(nbytes + 4); // overallocate by 4 bytes
*(Pool**)ans = NULL; // use NULL in the global new
return (char*)ans + 4; // don't let users see the Pool*
}
这里
我花了一个多小时试图弄明白什么是*(Pool**)ans=NULL代码>可以。
ans
是一个空指针,因此我假设它被强制转换为Pool
指针,并且Pool被设置为0。不是指针而是池本身,因为左边的第三个*
。但是池没有定义运算符=
声明中的指针**
显然是指向指针的指针。。。但在这种情况下,这对我来说毫无意义,因为ans
是一个单指针。这里使用Pool**
的唯一原因是语义正确性,因为“隐藏”的4字节头应该是指向池的指针(因此ans
是指向池的指针,并且*(池**)ans
具有类型池*
)
除非您能够将池
分配给空
,否则无法执行*(Pool*)ans=NULL
,而这可能不是此处的预期效果。类似于*(int**)ans=NULL
或更荒谬的*(Pool*****)ans=NULL
将具有相同的最终效果,但如果它最终是指向池的指针,则在语义上会很奇怪
一天结束时,您将得到:
+---+---+---+---+- - -
| 0 | 0 | 0 | 0 | ... and nbytes more bytes
+---+---+---+---+- - -
^ ans ^ returned address (ans + 4)
其中,前4个字节是指向某个池的指针
另一种思考方法是忽略整个<代码> nBys<代码>,考虑这个一般模式:
void * ptr = malloc(sizeof(TYPE));
*(TYPE *)ptr = VALUE;
这应该是有意义的。现在,如果类型是一个Pool*
,值是NULL
,并且您将其放入该模式中,您可以看到这一切仍然是有意义的:
void * ptr = malloc(sizeof(Pool *));
*(Pool **)ptr = NULL;
在你的例子中,你基本上仍然在这样做,虽然你在最后分配了一些额外的字节,但这与这里的类型无关
另一方面,它可能会在这里(而且在语义上是懒惰的)制造麻烦,到处硬编码4
,而不是sizeof(Pool*)
不,它不是“强制转换到池指针”。强制转换是:
(Pool**)
这不是指向池
的指针。这是指向池
的指针
现在,让我们假设ans
是一个池**
,因为它就是这样。在这种情况下:
*ans = NULL;
这将设置ans
所指向的指针,指向NULL
。不是Pool
类的某个制造实例,而是指向它的指针
但这里有一个更大的问题:
void* ans = malloc(nbytes + 4); // overallocate by 4 bytes
*(Pool**)ans = NULL; // use NULL in the global new
return (char*)ans + 4; // don't let users see the Pool*
这是一段非常古老的代码,它只有在指针长度为4字节时才能工作
在现代64位平台上,使用8字节长的指针,整个过程将失败得很惨……这不是“奇数”。是代码假设指向对象的所有指针都是4字节(通常为32位)和相关对齐方式。4
可能最好重写为sizeof(Pool*)
。或者完全删除它-偏移量更像是一个肮脏的把戏(程序员试图添加一个伪安全措施),并且没有实现太多的实际用途。(如果删除它,还可以修改直接操作池的其他函数,因为它们也会使用偏移量)。@Peter Sam键入“OLD”而不是“ODD”。