简体   繁体   English

uint64_t 类型的参数与 void* 类型的参数不兼容

[英]Argument of type uint64_t is incompatible with parameter of type void*

I have a function foo(void* pBuf).我有一个函数 foo(void* pBuf)。 I need to pass it a 64 bit address but I can't seem to get the right typecast when I'm passing by value.我需要向它传递一个 64 位地址,但是当我通过值传递时,我似乎无法获得正确的类型转换。

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

EDIT: Compiling using an ARM compiler.编辑:使用 ARM 编译器进行编译。

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

I'm on a 32-bit ARM and sizeof(void *) is 4我在 32 位 ARM 上并且sizeof(void *)4

Clarification: Why I needed a 64-bit address on a 32-bit ARM?说明:为什么我在 32 位 ARM 上需要 64 位地址? Because my memory map uses 36-bit addressing.因为我的内存映射使用 36 位寻址。

Call it this way: 这样称呼:

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

That is, you cast the address to a void-pointer to be compatible with the function signature. 也就是说,你的地址为void指针要与函数签名不兼容。

You should not use a 64-bits type for an address, as it is undefined behavior for 32-bits (or any non-64 bits) systems. 您不应为地址使用64位类型,因为对于32位(或任何非64位)系统,这是未定义的行为。

Rather, prefer using uintptr_t , which is standard C. See this question for more details or this page for references. 相反,更喜欢使用标准C的uintptr_t 。有关更多详细信息,请参uintptr_t 问题 ;有关参考,请参见本页

Then a solution could be : 那么一个解决方案可能是:

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

Note : if uintptr_t is not available on your system, size_t is usually a good second choice. 注意:如果uintptr_t在您的系统上不可用,则size_t通常是不错的第二选择。

Part 2 : 第2部分 :

Looks like, in your rephrased question, you want to convert an address into a 64-bits integer. 看起来,在您改写的问题中,您想要将地址转换为64位整数。

In which case, a direct cast from ptr to integer is likely to trigger a compiler warning, due to potential differences in wideness. 在这种情况下,由于宽度上的潜在差异,从ptr直接转换为整数很可能会触发编译器警告。

Prefer a double cast : uint64_t value = (uint64_t)(size_t) ptr; 最好使用double uint64_t value = (uint64_t)(size_t) ptr;uint64_t value = (uint64_t)(size_t) ptr;

I can think of two ways to get this right. 我可以想到两种方法来解决这个问题。 Got a solution to my problem by calling foo the first way 通过第一种方法调用foo来解决我的问题

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

This works only because my input to foo is always a 32-bit value. 这仅起作用是因为我对foo的输入始终是32位值。 The returned value can be 64-bit. 返回的值可以是64位。

  1. Of course, a proper fix would be to change foo itself, if I could modify it. 当然,如果可以修改foo,一个正确的解决方法是更改​​foo本身。 I could just pass foo(&address). 我可以通过foo(&address)。 Inside foo, retAddr = *pBuf. 在foo内部,retAddr = * pBuf。

Thanks for all the suggestions! 感谢所有的建议!

Sorry to necro this question, but none of these answers seem reasonable to me.很抱歉解决这个问题,但这些答案对我来说似乎都不合理。 This is a fairly straightforward type conversion problem.这是一个相当简单的类型转换问题。 It seems as though people were caught up on 64-bit addressing on a 32-bit system, when this could easily be for a peripheral or some other address space besides the system itself.似乎人们在 32 位系统上陷入了 64 位寻址,而这很容易用于外围设备或除系统本身之外的其他一些地址空间。

In the OP's case, a cast directly to uint64_t would cause undefined behavior because of the additional four bytes that do not exist in void * .在 OP 的情况下,直接转换为uint64_t会导致未定义的行为,因为void *不存在额外的四个字节。 In the case of the M4 calling convention, p would typically be passed in a single register, likely r0 .在 M4 调用约定的情况下, p通常会在单个寄存器中传递,可能是r0 There are no additional upper bytes for uint64_t to alias, so your compiler is rightly issuing a warning for this. uint64_t没有额外的高位字节作为别名,因此您的编译器正确地为此发出警告。

Under the GCC 7.3 arm-none-eabi port, void * can be safely cast to size_t (aka unsigned int ) because they both have size and alignment of 4 .在 GCC 7.3 arm-none-eabi端口下, void *可以安全地转换为size_t (又名unsigned int ),因为它们的大小和对齐方式都是4 Once that is done, you can safely promote unsigned int to uint64_t (aka unsigned long long int ) by assignment.完成后,您可以通过赋值安全地将unsigned int提升为uint64_t (又名unsigned long long int )。 The promotion is better defined behavior than a cast.提升是比演员更明确的行为。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM