是否有一种可移植的方法来在 C/C++ 中实现标记指针,例如一些跨平台和编译器工作的记录宏?或者,当您标记指针时,您自己会面临危险吗?如果存在这样的辅助函数/宏,它们是任何标准的一部分还是仅作为开源库提供?
对于那些不知道标记指针是什么但感兴趣的人来说,这是一种在普通指针中存储一些额外数据的方法,因为在大多数体系结构上,指针中的某些位始终为 0 或 1,因此您可以保留标志/类型/ 提示这些额外的位,并在您想要使用指针取消引用某些实际值之前擦除它们。
const int gc_flag = 1;
const int flag_mask = 7; // aka 0b00000000000111, because on some theoretical CPU under some arbitrary OS compiled with some random compiler and using some particular malloc last three bits are always zero in pointers.
struct value {
void *data;
};
struct value val;
val.data = &data | gc_flag;
int data = *(int*)(val.data & flag_mask);
Run Code Online (Sandbox Code Playgroud)
You can get the lowest N bits of an address for your personal use by guaranteeing that the objects are aligned to multiples of 1 << N. This can be achieved platform-independently by different ways (alignas and aligned_storage for stack-based objects or std::aligned_alloc for dynamic objects), depending on what you want to achieve:
struct Data { ... };
alignas(1 << 4) Data d; // 4-bits, 16-byte alignment
assert(reinterpret_cast<std::uintptr_t>(&d) % 16 == 0);
// dynamic (preferably with a unique_ptr or alike)
void* ptr = std::aligned_alloc(1 << 4, sizeof(Data));
auto obj = new (ptr) Data;
...
obj->~Data();
std::free(ptr);
Run Code Online (Sandbox Code Playgroud)
You pay by throwing away a lot of memory, exponentionally growing with the number of bits required. Also, if you plan to allocate many of such objects contiguously, such an array won't fit in the processor's cacheline for comparatively small arrays, possibly slowing down the program considerably. This solution therefore is not to scale.