簡體   English   中英

安全地將void *強制轉換為int

[英]Safely cast void* to int

如果將應用程序編譯為產生x32圖像,則取決於體系結構的整數類型可能是16位寬,32s位寬或大於2個字節的任何值。 void*大小將為4(在x32上始終為4 ???)。 這意味着將int傳遞給void*是可以的,但是如果發現在給定的體系結構上, void*int寬(標准僅保證int至少為2個字節)。

C標准n1124§6.3.2.3指針

5整數可以轉換為任何指針類型。 除非先前指定,否則結果是實現定義的,可能未正確對齊,可能未指向引用類型的實體,並且可能是陷阱表示形式。56)

6任何指針類型都可以轉換為整數類型。 除非先前指定,否則結果是實現定義的。 如果結果不能用整數類型表示,則行為是不確定的。 結果不必在任何整數類型的值范圍內。

在以下代碼段中將void*強制轉換為int可能會產生不確定的行為。

typedef enum tagENUM
{
    WSO_1,
    WSO_2,
    //...
    WSO_COUNT
} ENUM;

/* I cannot change handler signature because this is callback. I have to cast void*
 * to ENUM however inside */
void handler( int i, int j, void *user_data)
{
    ENUM mOperation;
    mOperation = (ENUM)reinterpret_cast<int>(user_data);
}

// somewhere
handler( 1, 2, (void*)WSO_1);  // UB? We can imagine that someone passes to handler
                               // (void*)WSO_131072 which don't fit into 16 bits
                               // So is there a place opened for UB?

如果這是正確的,那就打開了可能發生鼻粘膜重症的問題-我該如何安全地寫出這個問題呢? 我可以使用intptr_t來確保結果適合嗎?

void handler( int i, int j, void *user_data)
{
    ENUM mOperation;

uintptr_t p_mOperation = reinterpret_cast<uintptr_t>( user_data);

if ( p_mOperation > WSO_COUNT ) {
    send_error(conn, 500, http_500_error, "Error: %s", strerror(ERRNO));
    return;
}

mOperation = static_cast<ENUM_WS_OPERATION>( p_mOperation);  // now safe?

是的,它可能導致不確定的行為。 如果改用intptr_t ,則沒有未定義的行為。

但是,通常您可以重寫代碼,以使指針指向預期的整數,而不是強制轉換為整數。

在第二個示例中,您有一個雜燴。 您想使用intptr_tvoid *指向int 不是intptr_t *uintptr_t *

我的首選解決方案是user_data始終指向數據; 指向的數據類型由調用的處理程序或其他參數確定。

這一點:

mOperation = (ENUM)reinterpret_cast<int>(user_data);

提示您已經無法控制自己在做什么。 您正在執行兩次強制轉換,這始終表明發生了不良情況(好像reinterpret_cast尚未表明這一點)。

從這還不清楚您要做什么。 當然(void *)對於傳遞不是數據的值是不適當的強制轉換。 它用於傳遞指向任意數據緩沖區的指針,在那里人們希望另一端的東西可以從數據中得出所需的信息。

所以這:

handler( 1, 2, (void*)WSO_1); 

完全是錯誤的。

但是,鑒於WSO_1實際上是一個enum ,而且我不知道void *實際上小於枚舉的任何平台,您應該可以這樣做

mOperation = reinterpret_cast<ENUM>(user_data);

當客戶將枚舉類型轉換為空*時,該客戶已經進入了可疑區域,並且該轉換不會使情況變得更糟。

暫無
暫無

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

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