【问题标题】:How to cast volatile int** to void**如何将 volatile int** 转换为 void**
【发布时间】:2021-09-06 20:54:08
【问题描述】:

我有这个旧的 C 代码,我的编译器警告我(旧的 C 风格转换)。

volatile uint32_t* map;
void** argForSomeAPIfunction = (void**)↦

如何将其转换为 C++ 演员表风格?我需要将 volatile uint32_t** 转换为 void**。

我需要这个的原因是有一个闭源供应商 API 期望我传递一个 void** 指针。我无法更改该函数签名。另一方面,供应商告诉我,我可以使用指向 uint32_t 的指针访问这个始终为 32 位的寄存器映射,他为我提供了 C 风格的工作示例,它使用了 (void**)&。我尝试了这个 C 示例,它工作正常。

旁注:此供应商 API 通过自定义内核模块与 PCIe 卡进行通信。有两种选择读取 PCIe 卡的内部存储器,使用使用“ioctl”和内置检查的安全 API 函数,或者使用对这个 32 位寄存器映射的无监督访问,通过调用 @ 来初始化987654323@。这仅在程序开始时执行一次。之后,我使用 map[offset] 直接访问内存,其中偏移量以 4 个字节为步长,而不是监督函数 API::ReadRegister(offset) 在某些情况下速度较慢并且严重延迟数据采集(而卡正在执行其他任务) )。计算机不会更改寄存器内容,它只是读取这些内容。外部独立卡可以随时更改寄存器内容,所以我相信厂商在示例中引入了关键字volatile。

【问题讨论】:

  • 你正在做的是总是一个无效的演员和代码不正确。
  • 我希望我能看到更多的上下文,因为这个 volatile uint32_t* map; 闻起来不太好,第二行让它变得更糟。
  • @AnttiHaapala:如果您简要指出原因,我会得到帮助(OP 也是如此)
  • 我现在添加了更多上下文。 C 代码来自供应商的示例,我试过了,它工作正常,结果与完全监督函数相同,但速度更快。
  • 您的供应商似乎不称职。 “抛弃”volatile 始终是一个未定义的行为错误,进而可能导致生成不正确的机器代码。

标签: c++ c casting


【解决方案1】:

如果这是用于初始化,那么我猜它的作用是 填充void * 中,而不是其他任何东西,即好像在 C++ 中你有一个 void *& 类型的参数.

我相信它的目的是用作

void *ptr;
if (API::InitializeRegisterMap(&ptr)) {
    ...
}

然后之后您将获取ptr中的值并将那个转换为 volatile uint32_t *map

void *ptr;
volatile std::uint32_t *map;
if (API::InitializeRegisterMap(&ptr)) {
    map = static_cast<std::uint32_t *>(ptr);
}

最值得注意的是,在 C 中,与 C++ 不同的是,这可以写成完全无铸造,这应该被认为是一个好兆头。

另外,你想避免reinterpret_cast 像瘟疫一样。

【讨论】:

    【解决方案2】:

    经过几次试错步骤,我注意到这不能通过简单的转换步骤来完成,您需要连接两个:

    void** argForSomeAPIfunction = reinterpret_cast<void**>(const_cast<uint32_t**>(&map));
    

    需要内部的一个来摆脱易失性,第二个是从int转换为void。

    【讨论】:

    • 有很多方法可以将一个指针转换为另一个指针,但最终是否得到一个有效指针是另一个问题。您可以将结果指针转换回其原始类型,但我怀疑您是否可以用它做任何其他事情
    • 我现在在我的问题中提供了更多背景信息。我需要将此指针转换为 void**,我不能以任何其他方式执行此操作,因为 API 来自供应商并且已关闭。我只是想将供应商提供的示例从 C 改编为 C++。目前,我测试了这两个版本,它们似乎都可以工作,但当然可能存在一些极端情况,即这种无监督访问功能没有得到很好的定义。
    • 原始指针是volatile 是有原因的,在这种情况下你根本无法转换。或者它不是 volatile 出于任何充分的理由,在这种情况下,您需要将其删除。无论哪种情况,这都是错误的解决方案。
    • 您对此的感知需求尚不清楚,但请确保您了解void ** 不是一个通用双指针,因为void * 是一个通用单指针。 void ** 指向一个对象,该对象专门是 void *,而不是任何其他类型。
    • John,我无法更改供应商 API,它需要一个 void** 并且他们确保我在幕后使用它,就好像它是 32 位数据一样(是的,他们应该问而是将 int** 作为参数,但这是我无法更改的)。我可以改变的是他们给我的访问示例。 @Lundin,您是否建议最好只使用而不使用 volatile: uint32_t* 映射; void** argForSomeAPIfunction = reinterpret_cast(&map); ?
    猜你喜欢
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多