2011-02-07 86 views
0

或者,也許我不應該施放。這是我在做什麼:如何安全地將void *轉換爲C中的int?

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

我想與庫連接的驅動程序使用int將句柄存儲到其通道(因爲它們是通過調用open()調用返回的文件描述符)。所以,在我的代碼中,我從庫中傳入void *,並且需要使用int從驅動程序調用東西,反之亦然。碘。E:

// 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. 
} 

別人寫了實際存儲一些結構等地方,並只投三分球之間的適配器,所以沒有大小的問題出現。就我而言,我並不想管理文件描述符,因爲操作系統已經做到了。在我的電腦上,我認爲指針大於int,所以我可以找到擺脫這種方式的方法,但代碼也進入了嵌入式系統,而且我沒有足夠的經驗來完成任何工作關於這些機器上的類型的大小的假設。

+1

看到全部大寫「CAN_HANDLE」讓我對LOLCODE記憶中的笑話:)不批評你的代碼... – 2011-02-07 15:46:53

+0

是的,我也笑了。該庫充滿了這一點:can_open,can_send等(這是一個CAN總線庫):) – 2011-02-07 15:49:11

回答

3

編輯:當然,你不需要一個結構,你可以爲一個純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); 
} 
2

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

基於這個假設,只要sizeof(void *)> = sizeof(int),在這些類型之間進行轉換將是安全的,因爲您確信它確實是一個int類型。

如果你不能保證尺寸條件,或不想依賴破解,你應該爲int分配內存並返回該內存的地址。例如,您可以使用malloc()或在固定大小的數組中分配一個int。缺點是,當不再需要時,你需要釋放內存。我想象當驅動程序不再需要數據結構時,驅動程序會發出某種通知,告知您的代碼。

0

一般來說嵌入式系統,下面的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 

通常,地址總線將總是> =比數據總線。我想不出哪裏的數據總線會比地址總線大。

這裏有一個有點骯髒伎倆,可能會或可能不會解決問題:

typedef union 
{ 
    CAN_HANDLE handle; 
    long  value; 

} CAN_HANDLE_t; 

這應該是相當便攜的,即使你可能將不得不適應這個聯盟,以特定的系統(遠指針等) 。

相關問題