在C中无效指向结构指针

6 c struct pointers

我正在学习C,主要是K&R,但现在我找到了面向对象的C pdf教程,我很着迷.我正在经历它,但我的C技能/知识可能无法完成任务.这是教程:http://www.planetpdf.com/codecuts/pdfs/ooc.pdf

我的问题来自于在pdf的前几章中查看许多不同的功能.下面是其中之一.(pdf的第14页)

void delete(void * self){
     const struct Class ** cp = self;

     if (self&&*cp&&(*cp)->dtor)
                self = (*cp)->dtor(self);
     free(self);

 }
Run Code Online (Sandbox Code Playgroud)

dtor是一个析构函数指针.但是对于我的问题,对此的了解并不是必需的.

  • 我的第一个问题是,为什么**cp不变?它是必要的还是只是彻底的,所以代码编写者不会做任何意外损坏的事情?
  • 其次,为什么cp指向指针(双星号?).struct类在pdf的第12页上定义.我不明白为什么它不能成为单个指针,因为我们正在将自指针转换为类指针.
  • 第三,如何将void指针更改为Class指针(或指向类指针的指针)?我认为这个问题大多表明我对C的理解不足.我想象中的是一个空指针占用一定量的内存,但它必须小于Class指针,因为一个Class有很多"东西"在里面.我知道一个void指针可以"强制转换"到另一种类型的指针,但我不明白如何,因为可能没有足够的内存来执行此操作.

提前致谢

del*_*ver 3

有趣的pdf.

\n\n
\n

我的第一个问题是,为什么 **cp 是恒定的?是否有必要或只是彻底,以便代码编写者不会无意中做出任何破坏性的事情?

\n
\n\n

这是必要的,这样作者就不会意外地做任何事情,是的,并且向读者传达有关指针的性质及其用途的信息代码的

\n\n
\n

其次,为什么 cp 是一个指向指针的指针(双星号?)。结构体类在 pdf 第 12 页上定义。我不明白为什么它不能是单个指针,因为我们似乎将 self 指针转换为类指针。

\n
\n\n

看一下new()(第 13 页)创建指针的定义(与传递给p的指针相同的指针)selfdelete()):

\n\n
void * new (const void * _class, ...)\n{\n    const struct Class * class = _class;\n    void * p = calloc(1, class \xe2\x80\x94> size);\n    * (const struct Class **) p = class;\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,为“p”分配了空间,然后取消引用并分配了一个指针值(类中的地址;这就像取消引用并分配给 int 指针,但我们分配的不是 int,而是地址)。 这意味着 p 中的第一件事是指向其类定义的指针。 然而,p 被分配的空间不仅仅如此(它还将保存对象的实例数据)。现在考虑delete()再考虑一下:

\n\n
 const struct Class ** cp = self;\n if (self&&*cp&&(*cp)->dtor)\n
Run Code Online (Sandbox Code Playgroud)\n\n

当 cp 被取消引用时,由于它是一个指向指针的指针,所以它现在是一个指针。指针包含什么?一个地址。什么地址? 指向类定义的指针该类定义位于 p 所指向的块的开头。

\n\n

这有点聪明,因为 p\ 并不是真正指向指针的指针——它分配了更大的内存块,其中包含特定的对象数据。但是,该块的开头是一个地址(类定义的地址),因此如果 p 被取消引用为指针(通过转换或 cp),您就可以访问该定义。因此,类定义仅存在于一个位置,但该类的每个实例都包含对该定义的引用。合理?如果 p 被输入为这样的结构会更清楚:

\n\n
struct object {\n  struct class *class;\n    [...]\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后你可以使用类似的东西p->class->dtor()来代替现有的代码delete(). 然而,这会使整体情况变得混乱并使复杂化。

\n\n
\n

第三,如何将 void 指针更改为类指针(或指向类指针的指针)?我觉得这个问题最能说明我对C的缺乏理解。我脑子里想象的是一个void指针占用了一定的内存,但它一定小于Class指针,因为a\xe3 \x80\x80Class 里面有很多“东西”。

\n
\n\n

指针就像一个 int —— 它有一个小的、固定的大小来保存一个值。该值是内存地址。当您取消引用指针(通过*->)时,您访问的是该地址处的内存。但由于内存地址的长度都相同(例如,64 位系统上为 8 字节),因此无论类型如何,指针本身的大小都相同。这就是对象指针“p”的神奇原理。重申一下:内存块中指向的第一件事p是一个地址,它允许它充当指向指针的指针,当取消引用时,您将获得包含类定义的内存块,即与实例数据分开p

\n