簡體   English   中英

如何安全地將void *強制轉換為C中的int?

[英]How do I safely cast a void* to an int in C?

也許,我不應該投。 這是我在做什么:

我正在寫一段代碼,將Linux設備驅動程序鏈接到更高級別的庫。 庫的作者使用void * (通過typedef以新名稱)將句柄存儲到描述通信通道的特定於實現的對象。

我想與該庫連接的驅動程序使用int來存儲其通道的句柄(因為它們是open()調用返回的文件描述符)。 因此,在我的代碼中,我從庫傳遞了void * ,並且需要使用int從驅動程序中調用東西,反之亦然。 即:

// somewhere in the library ...
typedef void* CAN_HANDLE;

// ... in my code
CAN_HANDLE canOpen_driver(s_BOARD *board)
{
  int fd;
  // ...
  fd = open(busname, O_RDWR);
  // ...
  return (CAN_HANDLE) fd; // <-- not safe, especially not when converting back.
}

其他人編寫的適配器實際上將某些struct等存儲在某個位置,並且僅在指針之間進行轉換,因此不會出現大小問題。 就我而言,我真的不想像操作系統那樣管理文件描述符。

在我的PC上,我認為指針大於int ,所以我可以稍微修改一下一下,但代碼也進入嵌入式系統,而且我沒有足夠的經驗來假設大小這些機器上的類型。

編輯:當然,您不需要結構,您可以只為一個簡單的int分配內存。

CAN_HANDLE canOpen_driver(s_BOARD *board)
{
  int *fd = malloc(sizeof(int));
  if (fd)
  {
    // ...
    *fd = open(busname, O_RDWR);
    // ...
    return (CAN_HANDLE) fd;
  } 

  // failure
  return NULL;
}

假設存在一個匹配的清理呼叫。 就像是:

void canClose_driver(CAN_HANDLE handle)
{
  int *fd = handle;
  free(fd);
}

根據體系結構,您可能會擺脫它。 如果我正確理解,驅動程序將不會真正使用您提供給它的void *。 它只是存儲它,以便稍后將其傳遞回您的代碼。

基於該假設,只要sizeof(void *)> = sizeof(int),就可以在這些類型之間進行強制轉換,因為您可以確定它確實是一個int。

如果您不能保證大小條件,或者不想依靠黑客,則應該為int分配內存並返回該內存的地址。 例如,您可以使用malloc()或在固定大小的數組中分配int。 缺點是,當不再需要該內存時,您將需要釋放該內存。 我想象驅動程序有某種通知,可以在不再需要數據結構時向您的代碼發出信號。

通常,在嵌入式系統上,以下CPU模型是最常見的:

Data bus   Address bus   

 8 bit     16 bit  
 8 bit     16+8 bit (banking) 
16 bit     16 bit 
16 bit     16+8 bit (banking) 
32 bit     32 bit

通常,地址總線將始終大於數據總線。 我想不出任何CPU的數據總線會比地址總線大。

這是一個有點骯臟的技巧,可能會也可能不會解決問題:

typedef union
{
  CAN_HANDLE  handle;
  long        value;

} CAN_HANDLE_t;

即使您可能必須使此聯合適用於特定系統(遠指針等),這也應該相當可移植。

暫無
暫無

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

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