簡體   English   中英

uint64_t 類型的參數與 void* 類型的參數不兼容

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

我有一個函數 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 位尋址。

這樣稱呼:

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

也就是說,你的地址為void指針要與函數簽名不兼容。

您不應為地址使用64位類型,因為對於32位(或任何非64位)系統,這是未定義的行為。

相反,更喜歡使用標准C的uintptr_t 。有關更多詳細信息,請參uintptr_t 問題 ;有關參考,請參見本頁

那么一個解決方案可能是:

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直接轉換為整數很可能會觸發編譯器警告。

最好使用double uint64_t value = (uint64_t)(size_t) ptr;uint64_t value = (uint64_t)(size_t) ptr;

我可以想到兩種方法來解決這個問題。 通過第一種方法調用foo來解決我的問題

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

這僅起作用是因為我對foo的輸入始終是32位值。 返回的值可以是64位。

  1. 當然,如果可以修改foo,一個正確的解決方法是更改​​foo本身。 我可以通過foo(&address)。 在foo內部,retAddr = * pBuf。

感謝所有的建議!

很抱歉解決這個問題,但這些答案對我來說似乎都不合理。 這是一個相當簡單的類型轉換問題。 似乎人們在 32 位系統上陷入了 64 位尋址,而這很容易用於外圍設備或除系統本身之外的其他一些地址空間。

在 OP 的情況下,直接轉換為uint64_t會導致未定義的行為,因為void *不存在額外的四個字節。 在 M4 調用約定的情況下, p通常會在單個寄存器中傳遞,可能是r0 uint64_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;
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM