Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 正在将指针转换为指针。。。指向指针?_C++_Pointers_Casting - Fatal编程技术网

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”。