我如何取消引用 C 中的 void*?
How can I dereference a void* in C?
我有一个名为 bins
的 void*
数组。每个 void*
指向一个 chunk.
块
每个块由连续内存中依次放置的三样东西组成:
- 块的大小(以字节为单位)。这由
uint32_t
. 表示
- 下一个有效块的地址。这由
void*
. 表示
- 区块的数据。出于所有意图和目的,这是垃圾,可以忽略。
我想做什么
我的算法是这样工作的:
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
我有一个名为 bins
的 void*
数组。每个 void*
指向一个 chunk.
块
每个块由连续内存中依次放置的三样东西组成:
- 块的大小(以字节为单位)。这由
uint32_t
. 表示
- 下一个有效块的地址。这由
void*
. 表示
- 区块的数据。出于所有意图和目的,这是垃圾,可以忽略。
我想做什么
我的算法是这样工作的:
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