【问题标题】:Argument of type uint64_t is incompatible with parameter of type void*uint64_t 类型的参数与 void* 类型的参数不兼容
【发布时间】:2015-12-18 02:38:37
【问题描述】:

我有一个函数 foo(void* pBuf)。我需要传递一个 64 位地址,但是当我按值传递时,我似乎无法获得正确的类型转换。

示例:foo(地址)。其中- uint64_t 地址=0x00000000DEADBEEF

编辑:使用 ARM 编译器进行编译。

uint64_t foo(void *pBuf){
    uint64_t retAddr = (uint64_t) pBuf;
    retAddr += 0x100000;
    return retAddr;
}

我在 32 位 ARM 上,sizeof(void *)4

澄清:为什么我需要 32 位 ARM 上的 64 位地址? 因为我的内存映射使用 36 位寻址。

【问题讨论】:

  • address 是一个局部变量,其中包含我需要的地址。
  • 您需要详细说明您使用的是哪种系统以及foo 函数对其参数的作用
  • 你最新的代码示例有什么问题?我能猜到的唯一问题是某些编译器会通过直接从void* 转换为uint64_t 来发出警告。在这种情况下,更喜欢双重转换:(uint64_t)(size_t)
  • 问题在于编译对 foo 的调用。不是函数本身。
  • 如果address 不是以00000000 开头,您期望会发生什么? (请记住,您正在尝试将地址放入 32 位 void *

标签: c arm


【解决方案1】:

这样称呼:

uint64_t address = 0xDEADBEEF;
foo((void*)address);

也就是说,您将地址转换为空指针以与函数签名兼容。

【讨论】:

  • 这会在具有 32 位 void * 的系统上导致未定义的行为
  • @M.M:这无关紧要,因为 OP 已经说过他们有一个 64 位地址。 32 位系统没有 64 位地址。
  • @coder_mario:你说“不起作用”是什么意思?
  • 我明白了。错误:#171-D:类型转换无效
  • @coder_mario 你能调查一下sizeof(void *) 在你的系统上提供了什么吗?
【解决方案2】:

很抱歉回答这个问题,但这些答案对我来说似乎都不合理。这是一个相当简单的类型转换问题。似乎人们在 32 位系统上迷上了 64 位寻址,而这很容易用于外围设备或系统本身以外的其他地址空间。

在 OP 的情况下,直接转换为 uint64_t 会导致未定义的行为,因为在 void * 中不存在额外的四个字节。在 M4 调用约定的情况下,p 通常会在单个寄存器中传递,可能是r0uint64_t 没有额外的高字节作为别名,因此您的编译器对此发出警告是正确的。

在 GCC 7.3 arm-none-eabi 端口下,void * 可以安全地转换为 size_t (又名 unsigned int),因为它们的大小和对齐方式都是 4。完成后,您可以通过分配安全地将unsigned int 提升为uint64_t(又名unsigned long long int)。促销是比演员更明确的行为。

uint64_t foo(void *p){
    uint64_t a = (size_t) p;
    a += 0x100000;
    return a;
} 

【讨论】:

    【解决方案3】:

    您不应该对地址使用 64 位类型,因为对于 32 位(或任何非 64 位)系统来说,这是未定义的行为。

    相反,更喜欢使用uintptr_t,这是标准 C。 有关详细信息,请参阅this question 或参考this page

    那么解决方案可能是:

    uintptr_t address = 0xDEADBEEF;   /* will trigger a warning if the constant is > max possible memory size */
    foo((void*)address);
    

    注意:如果uintptr_t 在您的系统上不可用,size_t 通常是不错的第二选择。

    第2部分 :

    看起来,在您改写的问题中,您想将地址转换为 64 位整数。

    在这种情况下,由于宽度的潜在差异,从 ptr 直接转换为整数可能会触发编译器警告。

    更喜欢双重演员: uint64_t value = (uint64_t)(size_t) ptr;

    【讨论】:

    • 我确实需要 64 位地址来进行 AXI 寻址
    【解决方案4】:

    我可以想出两种方法来解决这个问题。通过第一种方式调用 foo 来解决我的问题

    1. foo((void*)(uint32_t)address)

    这只是因为我对 foo 的输入始终是 32 位值。返回值可以是 64 位。

    1. 当然,如果我可以修改它,一个适当的解决方法是更改​​ foo 本身。 我可以通过 foo(&address)。在 foo 内部,retAddr = *pBuf。

    感谢所有建议!

    【讨论】:

      猜你喜欢
      • 2014-02-08
      • 1970-01-01
      • 1970-01-01
      • 2018-09-07
      • 1970-01-01
      • 2021-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多