[英]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.