首页 > 解决方案 > 在编译时获取对象转换为算术类型的地址

问题描述

我正在尝试在 C++ 中实现 x86 页表/页目录,我希望能够在编译时构建它们。为了做到这一点,我需要能够在编译时获得静态 constexpr 页表对象的地址,转换为算术类型,这样我就可以使用它们来构造静态 constexpr 页目录条目,如下所示:

struct PageTable {
  /* ... */
};

struct PageDirectory {
  constexpr PageDirectory(std::initializer_list<uint32_t> entries)
  { /* ... */ }

  /* ... */
};

static constexpr PageTable pt { /* ... */ };

static constexpr PageDirectory pd {
  reinterpret_cast<uint32_t>(&pt) | WRITE | PRESENT,

  /* ... */
};

这不起作用,因为reinterpret_cast不能在常量表达式中使用。有没有其他方法可以实现这一点或类似的东西?

标签: c++c++17constexprpage-tables

解决方案


在编译时,通常不允许您进行低级诡计,例如访问地址的数值。如果源对象是(或包含)指针,即使C++20bit_cast也明确不是。constexpr

这很重要,因为运行时事物的地址与其编译时地址不同。实际上,构建系统中处理常量评估的部分(又名:编译器)与构建系统中处理分配地址的部分(又名:链接器)不同。由于编译器看不到未来,它无法计算编译时对象的运行时地址。

当然,还有一个事实是链接器本身可能不知道该地址是什么,因为现代操作系统通常将可执行文件分配给随可执行文件的每次加载而不同的任意虚拟地址。虽然链接器/操作系统不必这样做,但语言确实需要在设计时考虑到这一点。也就是说,它不能做一些使这些事情不可能或不可行的事情。


推荐阅读