在 constexpr 中将 'void*' 转换为 'unsigned int'

convert `void*` to `unsigned int` in constexpr

本文关键字:unsigned int 转换 constexpr void 中将      更新时间:2023-10-16

一个人不能在 constexpr 中做一个reinterpret_cast<unsigned int>(void*),所以我正在尝试类似的东西;

constexpr bool is_null(void* ptr)
{
    return ptr == nullptr;
}
constexpr unsigned int get_id(void* ptr)
{
    return is_null(ptr) ? 0 : 1 + get_id(static_cast<char*>(ptr) - 1);
}

但是我在编译时收到一个错误,关于 ptr == nullptr 不是 constexpr,但仅在递归调用中,而不是如果我删除它。那么,如果可能的话,如何在编译时将void*转换为unsigned int呢?

在编译时,地址常量表达式由"符号 + 加法"表示形式跟踪,例如:

int x[5];
constexpr int* p = x + 3 - 1;

假设int是 4 个字节,p是 symbol=x,addend=2*4=8 个字节。 p = x+8。

因此,您只能对具有相同符号的地址常量表达式执行指针操作,因为在转换过程中不知道它们的最终相对地址是什么。 此外,加法可能不会超出对象,主要是为了安全起见,但也因为您可能最终为 null。 例如,假设 x 在地址 4000 十进制处分配。 然后,x-1000 将是一个空指针表达式,但直到链接时才知道。

标准中的规则旨在支持这种表示。 可以对它们执行的常量操作反映了在此表示形式下可用的信息。

另请注意,非静态存储持续时间变量的绝对地址在链接时甚至未知,自动存储持续时间对象的堆栈相对地址与每个函数调用不同,动态存储持续时间对象在运行时确定堆地址。

相关文章: