从 uint8_t* 到 uint32_t 的转换无效 - 从 32 位架构迁移到 64 位架构时?

Invalid conversion from uint8_t* to uint32_t - when migrating from 32 to 64bit architecture?

我有一个小函数可以在 32 位架构上将虚拟内存地址转换为物理地址:

uint32_t VIRTBASE;

uint32_t getPhysForVirt(void* virt) {
  uint32_t offset = (uint8_t*)virt - VIRTBASE;
  return PHYSBASE + offset;
}

它在过去 10 多年中编译和运行时没有出现任何问题。

我更改了编译器以构建适用于较新架构的存储库(现在首次支持 64 位)。

编译失败说明

invalid conversion from ‘uint8_t*’ {aka ‘unsigned char*’} to ‘uint32_t’ {aka ‘unsigned int’} [-fpermissive]

现在,我理解了消息,但我不确定是否需要执行此编译而不会出错的必要步骤。

我唯一确定的是我不想启用 -fpermissive

您正在进行指针运算并将其直接转换为 32 位无符号整数。

在 32 位架构上,指针也是 32 位无符号整数,因此这可能在后台默默处理。

现在,在您的 64 位架构上,您要减去两个 64 位指针并将结果存储在一个 32 位整数中——因此会丢失一半的地址!

你可能根本不希望这个函数返回一个整数,而是一个指向你实际使用的任何数据类型的指针(大概 uint8_t*,因为函数中明确说明了这一点本身)。

编辑:相反,也许您实际上是想取消引用 virt 并减去它的值,而不是进行指针运算?如果是这样,您的 * 运算符放在了错误的位置。尝试:

  uint32_t offset = (uint8_t) *virt - VIRTBASE;

尽管正如另一位评论者指出的那样,这会导致取消引用 void 指针时出现问题。您必须先将其转换为有意义的内容。

您使用了错误的类型。 C 语言有特殊类型用于将指针转换为整数值。

uintptr_t VIRTBASE;

uintptr_t getPhysForVirt(const void * restrict virt) {
  ptrdiff_t offset = (uintptr_t)virt - VIRTBASE;
  return PHYSBASE + offset;
}

如果其余代码按照此函数的方式编写 - 圣诞节你有很多工作要做。