3

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

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,但仅在递归调用中,而不是在我删除它时。那么,如果可能的话,我如何在编译时将 a 转换为 avoid*unsigned int

4

1 回答 1

1

在编译时,地址常量表达式由“符号 + 加数”表示跟踪,例如:

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 将是一个空指针表达式,但直到链接时才知道。

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

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

于 2013-09-22T16:07:38.130 回答