【问题标题】:How can I dereference a void* in C?如何取消引用 C 中的 void*?
【发布时间】:2016-02-28 22:39:31
【问题描述】:

我有一个名为binsvoid*s 数组。每个void* 指向一个

每个块由三个在连续内存中依次排列的东西组成:

  1. 块的大小(以字节为单位)。这由 uint32_t 表示。
  2. 下一个有效块的地址。这由 void* 表示。
  3. 块的数据。出于所有意图和目的,这是垃圾,可以忽略。

我想做什么

我的算法是这样工作的:

if bins[index] == NULL: foo()
otherwise:
    save the address of this chunk (it is bins[index])
    get the address of the next chunk
    set bins[index] to the address of the next chunk
    return the original value bins[index] that we saved

我在获取下一个块的地址时遇到了很多麻烦。现在,我的实现有效,但它非常 hacky:

void* next = (void*)*(uint64_t*)(bin[index] + sizeof(uint32_t));

主要问题是在取消引用之前将地址 bin[index] + sizeof(uint32_t) 转换为 uint64_t。有什么方法可以取消引用它,就好像它是一个地址或一个指针?

【问题讨论】:

  • 你的块是structs 吗?这可能会有所帮助。
  • 你不能取消引用一个 void* 你需要将它转换回它之前的任何内容才能取消引用它。您的块应该封装在一个结构中,然后您可以转换回那个结构。你也有重复的努力。块的大小和下一个块的地址告诉你同样的事情。最好只保留大小。
  • 您必须使用void 对象。这在 C 中是不可能的。你有一个 XY 问题。没有冒犯,但请先下定决心要完成什么,并了解更多关于指针的知识(例如阅读 C 书籍);你似乎很困惑你真正想要什么以及 C 如何支持你。
  • 您将无法制作一系列不同大小的物品。您可能必须 malloc 块然后保存一个指针数组。

标签: c pointers dereference


【解决方案1】:

您可以定义一个具有 2 个成员的结构并转换指针:

struct chunk_head {
    uint32_t size;
    void *next;
};

void *next = ((struct chunk_head*)bins[index])->next;

这假设 void* 在 32 位上对齐。

一种更直接但可读性较差的方式是:

void *next = *(void**)((uint64_t*)bins[index] + 1);

您的方法是不可移植的,因为它依赖于 gcc 扩展的 void* 算术。标准 C 不允许将数字添加到 void*。另请注意,您读取了指向uint32_t 的指针并将其转换为void*,这与将地址转换为void** 并取消引用以读取void* 指针并不完全相同:

void *next = *(void**)(bin[index] + sizeof(uint32_t));  // gcc extension

【讨论】:

    猜你喜欢
    • 2014-07-23
    • 2011-06-17
    • 2012-05-23
    • 1970-01-01
    • 2014-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多