问题标签 [void-pointers]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
6 回答
1195 浏览

c - C 中指向 void 指针的指针 - 我可以将 void** 用于基本多态性吗?

我可以理解 avoid**可能在内存中的样子,但我想知道我是否正确使用它。我在下面描述的内容是否存在任何基本缺陷?例如,虽然我可以说“它对我有用”,但我是否以某种方式创建了糟糕/不可移植的代码?

所以我有一个小行星克隆。可以发射子弹的实体有 3 个,玩家 ( SHIP *player_1, SHIP *player_2) 和 UFO ( UFO *ufo)。当子弹发射时,知道是谁发射的子弹很重要;如果是玩家,当它击中某些东西时,他们的分数需要增加。所以,子弹将存储它属于什么类型的实体 ( owner_type) 以及直接指向所有者 ( owner) 的指针:

然后,当玩家按下按钮或 UFO 看到目标时,将调用以下函数之一:

...它们可能被称为,例如,像这样:

最后,当子弹击中目标(例如小行星)时,我们取消对所有者的引用。如果它是一艘船,我们可以在那里增加分数。

这似乎是一个合理的方法吗?就像我说的,它对我有用,但我只有几个月的 C 经验。

最后一点:为什么我不使用 avoid*而不是 a void**?因为我想避免悬空指针。换句话说,假设它player_1死了并且被释放了,但他们的子弹继续前进并击中了一颗小行星。如果我只有一个void*,则该hit_asteroid函数无法知道bullet->owner指向已取消分配的内存。但是使用 a void**,我可以有效地检查它是否为 NULL;如果player_1是 NULL,那么*bullet->owner也将是 NULL。

编辑:到目前为止,所有受访者都同意在这里使用 void** 可能不是必需的,因为我可以避免悬空指针问题(例如,仅通过静态分配基础对象)。他们是正确的,我会重构。但是我仍然有点想知道我是否以某种方式使用了 void** 可能会破坏某些东西,例如在内存分配/强制转换方面。但我想如果没有人举手宣布它有故障,它至少类似于技术上可行的东西。

谢谢!

0 投票
2 回答
1364 浏览

c++ - Ncurses 用户指针

我正在尝试学习 ncurses,并且正在阅读此处的精彩指南,但用户指针处的示例无法编译。尝试编译时出现此错误。

menu.cpp: In function 'int main()':

menu.cpp:44: error: invalid conversion from 'void (*)(char*)' to 'void*'

menu.cpp:44: error: initializing argument 2 of 'int set_item_userptr(ITEM*, void*)'

menu.cpp:70: error: invalid conversion from 'void*' to 'void (*)(char*)'

此外,您可能需要添加 cstdlib 和 cstring 才能使用 strlen 和 calloc 进行编译。

我对 void 指针了解不多,因此非常感谢您对修复示例的帮助。

谢谢

0 投票
1 回答
288 浏览

c - GLib 原子和内存块

以下代码片段来自The Official GNOME 2 Developer's Guide

  • 这是否意味着每个原子都是 42 字节,每个“内存块”包含42 16 个原子,并且40000/16=2500在运行上述代码时会创建内存块?

  • 他们为什么在这里使用 gchar* ?运行时是否会发生从 gpointer (void*) 到 gchar* 的隐式转换data[i] = g_mem_chunk_alloc(my_chunk);

  • 如果上述陈述为真,则每个 gchar* 指向 42 字节的内存。那么如何访问特定原子的所有字节呢?会data[7]+41是一个可用的内存位置吗?


  • 当我尝试编译代码 gcc 产生此错误消息:

    error: storage size of ‘my_chunk’ isn’t known 怎么了?

0 投票
3 回答
4009 浏览

c++ - 多重继承:从 void * 转换为第二个基类后的意外结果

我的程序需要使用 void* 在动态调用情况下传输数据或对象,以便它可以引用任意类型的数据,甚至是原始类型的数据。但是,我最近发现,在具有多个基类的类的情况下,向下转换这些 void* 的过程会失败,甚至在对这些向下转换的指针调用方法后使我的程序崩溃,即使内存地址似乎是正确的。崩溃发生在访问“vtable”期间。

所以我创建了一个小测试用例,环境是 Mac OS X 上的 gcc 4.2:

产生以下输出:

如您所见,“装饰(每个 void*)”结果是完全错误的。它也应该是 30,30,就像第一行一样。

无论我在 shape_cast() 中使用什么铸造方法,我总是会为 Decorated 部分获得相同的意外结果。这些 void *.

根据我对 C++ 的理解,这应该是可行的。有没有机会让它与 void* 一起工作?这可能是 gcc 中的错误吗?

谢谢

0 投票
5 回答
256 浏览

c - 关于我在 C 中使用 void* 作为动态数据类型的模块化代码的几个问题

几天前我发布了这个问题,每个人都建议我使用void*,我做到了。我认为他们中的一些人还指出了一些我需要注意的事情,但我不确定它们到底是什么。但是,我遇到了一些问题......

我不会将我所有的代码都发布在它很大的地方,相反,我会发布我认为重要的东西,希望足以让你帮助我。

我的哈希表结构是这样的:

我的插入函数的签名是这样的:

在该函数内部的某个地方,当我在哈希表中找到一个空闲存储桶时,我会这样做:

所有这些都带来了一些问题:

1)正如您在上面看到的,我只是将空闲存储桶的每个键/值对设置为与键/值hashInsert函数参数传递的相同指针。这带来了一个问题,您可能已经注意到了......例如,做这样的事情:

如果输入是“KeyA”,然后是“KeyB”,则两者都将“KeyB”作为存储桶键。同样的事情适用于值而不仅仅是键,因为它们基本上是相同的类型,因为我想让我的代码完全模块化,适用于任何数据类型。

我怎么能解决这个问题?

我的第一个想法是使用strdup(str)并将其传递给hashInsert函数。那将解决问题。由于这是在主代码中处理的,因此我也可以轻松地将malloc()其用于需要作为值传递的任何其他数据类型(键可能始终是字符串或 int)。

但是这个解决方案带来了另一个问题......

2)我应该如何释放这个分配的内存?当然,它是由“主程序员”而不是“哈希表模块程序员”分配的,所以“主程序员”应该在主代码中释放它,对吧?但是,对我来说,这看起来不像模块化代码。

我的代码还有一个hashDestroy功能,可以释放所有分配的内存。但是我怎样才能使用这个功能来释放一切呢?我不能只遍历每个键/值并free()在它们上使用,因为它们中的一些可能一开始就不是malloc'd任何程序员的,我不需要释放它们。

我怎样才能知道哪些是我hashDestroy必须免费的,哪些不应该?

3)最后,我想我也可以把这个问题混在一起......在第一点,我的建议是使用strdup()malloc“修复”那个特定问题(同时引入另一个问题),但这看起来也不是很模块化大部头书。这种内存分配应该在哈希表模块代码中完成,而不是由“主程序员”在主代码中完成。

你建议我如何解决这个问题?我的意思是,数据类型可以是任何东西,虽然使用strdup()有很大帮助,但它只适用于字符串。如果我需要为某些特定结构或只是一个 int 分配内存怎么办?

很抱歉这篇大文章,但我认为这些问题都是相关的,我需要一些帮助来弄清楚它们,因为我的 C 知识并不是那么极端。我最近才知道void*所以...

0 投票
2 回答
2032 浏览

com - 使用 ATL 和 IUnknownPtr 时正确的转换方法是什么?

在修改现有 ATL COM 对象的过程中,我看到了一篇来自“The Old New Thing”博客的文章,名为“人们搞砸 IUnknown::QueryInterface 的方式”,评论部分开始讨论其中一个受访者 (Norman Diamond) 指出,在文章的一个示例中,强制转换为 void** 是不正确的。

但是,当我尝试纠正我的代码以正确进行转换时,我最终会出现内存泄漏。

示例如下:

诺曼说

朋克不是虚无*。朋克是一个未知数*。

void** 不是通用指针类型。void* 是一种通用指针类型,并且 char* 和亲戚以这种方式被视为等价,但 void** 不是。

如果你想遵守调用约定并避免可怕的死亡,你必须这样做:IUnknown *punk; 无效*朋克无效;psf->QueryInterface(IID_IUnknown, &punkvoid); 朋克 = (IUnknown *)punkvoid;

许多其他 MSDN 贡献者犯了同样的错误……有些人可能会说它在迄今为止的所有 VC++ 实现中都有效,但这并不能使它成为正确的代码,而且它仍然违反了调用约定。

鉴于此,我去更改我的旧代码 - 如下:

然后我将其更改如下:

但是现在我的应用程序有一个来自 COM 对象的内存泄漏

0 投票
5 回答
16093 浏览

c++ - 等效于 C++ 的 window.setTimeout()

在 javascript 中有这个甜蜜的函数window.setTimeout( func, 1000 ) ;,它将在 1000 毫秒后异步调用。func

我想在 C++ 中做类似的事情(没有多线程),所以我把一个示例循环放在一起:

我怎样才能使这样的工作?

0 投票
2 回答
5928 浏览

c - 使用 void 指针作为函数参数的问题

看不懂这个结果。。。

编码:

我打这个电话:bar(900011009);

printf()输出是:

我真的需要key成为一个空指针,我该如何解决这个问题?

0 投票
4 回答
11411 浏览

c - C:从 void 指针推断类型

假设一个函数将 void 指针作为参数,如下所示:int func(void *p);
我们如何确定或猜测 p 指向的类型?

0 投票
2 回答
2522 浏览

c++ - C++中的空指针

我写了这个qsort:

当我打电话时

它说从 char** 到 void** 的无效转换。为什么这是错误的?

这是代码: