将指针指向指针......指针?

时间:2016-09-10 22:57:33

标签: 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 in the global new
  return (char*)ans + 4;           // don't let users see the Pool*
}

此处https://isocpp.org/wiki/faq/dtors

我花了一个多小时现在试着了解*(Pool**)ans = NULL;做了什么。 ans是一个void指针,所以我假设它被强制转换为Pool指针并且池设置为0.不是指针而是池本身,因为第三个*在左边。但是Pool没有定义operator=

声明中的

pointer**显然是指向指针的指针......但在这种情况下,这对我没有意义,因为ans是一个指针。

2 个答案:

答案 0 :(得分:6)

这里使用Pool**的唯一原因是语义正确,因为大概是“隐藏的”4字节头应该是指向Pool的指针(所以ans是一个指向Pool的指针,*(Pool **)ans的类型为Pool *)。

除非您能够将*(Pool *)ans = NULL分配给Pool,否则无法执行NULL,这可能无论如何都不是预期的效果。像*(int **)ans = NULL或更荒谬的*(Pool ******)ans = NULL这样的东西会产生相同的最终效果,但如果它最终是指向Pool的指针,那么它在语义上会很奇怪。

在一天结束时,你最终会得到:

 +---+---+---+---+- - -
 | 0 | 0 | 0 | 0 | ... and nbytes more bytes
 +---+---+---+---+- - -

 ^ ans           ^ returned address (ans + 4)

前4个字节的目标是指向Pool某处的指针。

考虑这一点的另一种方法是忽略整个nbytes的事情,考虑这种一般模式:

void * ptr = malloc(sizeof(TYPE));
*(TYPE *)ptr = VALUE;

这应该是有道理的。现在,如果TYPE是Pool *而VALUE是NULL并且您将其纳入该模式,那么您可以看到它仍然有意义:

void * ptr = malloc(sizeof(Pool *));
*(Pool **)ptr = NULL;

然后在你的情况下你仍然基本上这样做,虽然你在最后分配一些额外的字节,但这与这里的类型无关。

顺便说一句,它可能会在这里(以及语义上懒惰)在所有地方硬编码4,而不是sizeof(Pool *)

答案 1 :(得分:2)

不,它不是“强制转换为池指针”。演员是:

(Pool**)

这不是指向Pool的指针。这是指向Pool的指针。

所以,让我们假装ansPool **,因为它就是这样。在那种情况下:

*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个字节长的指针,整个事情都会失败......