我如何取消引用 C 中的 void*?

How can I dereference a void* in C?

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

每个块由连续内存中依次放置的三样东西组成:

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

我想做什么

我的算法是这样工作的:

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。有什么方法可以将其取消引用,就好像它是地址或指针一样?

您可以定义一个包含 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);

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

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