void* 和 void** 的心智模型?

Posted

技术标签:

【中文标题】void* 和 void** 的心智模型?【英文标题】:Mental model for void* and void**? 【发布时间】:2011-08-01 07:26:17 【问题描述】:

注意:我是一名经验丰富的 C++ 程序员,所以我不需要任何指针基础知识。只是我从未与void** 合作过,并且很难将我的心智模型调整为void*void**。我希望有人能很好地解释这一点,以便我更容易记住语义。

考虑以下代码:(使用例如 VC++ 2005 编译)

int main() 
  int obj = 42;
  void* ptr_to_obj = &obj;
  void* addr_of_ptr_to_obj = &ptr_to_obj;
  void** ptr_to_ptr_to_obj = &ptr_to_obj;
  void* another_addr = ptr_to_ptr_to_obj[0];
  // another_addr+1; // not allowed : 'void*' unknown size
  ptr_to_ptr_to_obj+1; // allowed

【问题讨论】:

您的代码使用 gcc 4.5.2 编译得很好,即使是 another_addr+1; 部分。您能否添加您收到的错误消息? @Philip:我最近偶然发现有一个 GCC 扩展允许对 void* 进行算术运算。这就是为什么您不会收到 GCC 错误的原因。错误信息已经在评论中:'void*' unknown size 感谢您的澄清。伙计,我讨厌那些 GNU 的人... 【参考方案1】:

void* 是指向某物的指针,但你不知道是什么。因为你不知道它是什么,你不知道它占用了多少空间,所以你不能增加指针。

void** 是指向void* 的指针,所以它是指向指针的指针。我们知道空间指针占用了多少空间,因此我们可以递增 void** 指针以指向下一个指针。

【讨论】:

void* 是指向某物的指针,并且您通常确切地知道该物是什么(例如,int 的链接列表,由 void* 引用),或者您不知道不关心(例如从 void* 到 void* 的 memcpy 副本)。 可能是迄今为止最好的解释之一。 啊..简直太棒了:) 【参考方案2】:

void* 指向编译器未知类型的对象。

void** 指向一个存储void* 的变量。

【讨论】:

【参考方案3】:

void * 可以指向任何东西(函数除外)。所以它甚至可以指向指针,所以它甚至可以指向其他void * 对象。

void ** 是指向void * 的指针,因此它只能用于指向void * 对象。

【讨论】:

【参考方案4】:

void 具有误导性,因为它听起来像 null。但是,最好将void 视为未指定的类型。所以void* 是未指定类型的指针,void** 是指向未指定类型的指针。

【讨论】:

“但是,最好将 void 视为未指定的类型。”在void* 的上下文中很好的解释,但应该明确限定该上下文,因为这对于返回类型、参数列表等是完全错误的。【参考方案5】:

void 是一个没有对象的类型。

void * 是传统的标量类型。

void ** 也是一种传统的标量类型,恰好指向void *


void * 可以用来指向任何东西,但我更喜欢只将它用于未初始化的存储。将void * 指向实际对象通常有更好的选择。

【讨论】:

在 C 中,void * 通常是实现“通用”函数的唯一实用方法。 @Oli:是的,我想我不确定这里的语言环境。 这是一种奇怪的心智模型

以上是关于void* 和 void** 的心智模型?的主要内容,如果未能解决你的问题,请参考以下文章

双过程理论与三重心智模型

心智模式

ChatGPT背后模型被证实具有人类心智!斯坦福新研究炸了,知名学者:“这一天终于来了”...

炼金术: 程序员的心智模型

Javascript 异步函数的“等待”的正确心智模型:生成器的“产量”与“promise.then()”?

区块链中的心智模型