【问题标题】:Get address of object cast to arithmetic type at compile time在编译时获取对象转换为算术类型的地址
【发布时间】:2021-12-20 05:07:21
【问题描述】:

我正在尝试在 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 不能在常量表达式中使用。有没有其他方法可以让我意识到这一点或类似的事情?

【问题讨论】:

  • @JaMiT 是的,修复了。
  • 似乎不可能。
  • @NicolBolas 我不明白这个问题,页面目录中的每个条目都包含页表的地址或与一些标志一起,因此需要这种转换。我可以对两者都使用纯 C 数组,但我希望它们是 C++ 类,而不是其 constexpr 构造函数做额外的事情。
  • @NicolBolas:我在写一个操作系统,运行时cr3会指向pdpd的第一个入口必须指向ptpd不需要访问pt的内容。

标签: c++ c++17 constexpr page-tables


【解决方案1】:

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

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

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

【讨论】:

  • 呵呵,我没想到会这样,但这是有道理的,所以这在概念上是不可能的。
猜你喜欢
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多