2010-05-27 67 views
5

工作的代碼庫中包含了一些代碼,看起來大致是這樣的:如何將二進制數據解釋爲整數?

#define DATA_LENGTH 64 

u_int32 SmartKey::SerialNumber() 
{ 
    unsigned char data[DATA_LENGTH]; 
    // ... initialized data buffer 
    return *(u_int32*)data; 
} 

此代碼工作正常,但GCC提供了以下警告:

warning: dereferencing pointer ‘serialNumber’ does break strict-aliasing rules 

有人能解釋一下這個警告?這個代碼有潛在危險嗎?如何改進?

更新
與感謝詹姆斯McNellis的回答,我想出了下面的效用函數:

template<class T, class Data> 
T BinaryCast(const Data & inData) 
{ 
    T ret; 
    std::copy(&inData[0], &inData[0] + sizeof(ret), reinterpret_cast<char*>(&ret)); 
    return ret; 
} 

u_int32 SmartKey::SerialNumber() 
{ 
    unsigned char data[DATA_LENGTH]; 
    // ... initialized data buffer 
    return BinaryCast<u_int32>(data); 
} 

隨意提出改進意見!

+0

可能與指針被從unsigned char *轉換爲u_int32 *,但自從我做C++以來很長一段時間。如果是這樣,由於DATA_LENGTH是32的精確倍數,所以不應該有問題。 – 2010-05-27 15:27:07

回答

11

該警告是因爲您違反了strict aliasing rule

一種方式正確地做到這一點是將字節從data緩衝器複製到一個u_int32對象,並返回該對象:

unsigned char data[DATA_LENGTH]; 
// ... initialized data buffer 

u_int32 i; 
assert(sizeof (i) <= DATA_LENGTH); 
std::copy(&data[0], &data[0] + sizeof (i), reinterpret_cast<char*>(&i)); 
return i; 

此解決方案,因爲在C++中它被允許訪問的任何類型的對象作爲數組char

std::copy()<algorithm>

+0

正是我想發佈的內容。儘管我的解決方案使用了memcpy。 – PeterK 2010-05-27 15:28:25

+1

即使你不使用STL,至少也要使用reinterpret_cast。 – user347594 2010-05-27 15:38:20

+0

每當以這種方式談論(排除)序列化數據時應該提及的一個微妙之處在於字節順序。蘋果公司使用英特爾芯片的情況並不多,但應該記住,以免數據嚴重損壞。 – user168715 2010-05-27 17:14:31

2

在C和C++語言重新解釋由一種類型的另一種類型的對象的對象佔據的存儲器是非法的 - 它會導致未定義的行爲。一些編譯器使用此規則執行激進的別名相關優化。因此,如果執行上述重新解釋,代碼可能無法按預期工作。

在C/C++中,將任何對象重新解釋爲char數組是可以的,但不能將獨立數組的char和reinterpret作爲其他類型的對象。這就是你的代碼在做什麼。

除了別名問題,您必須記住,獨立的自動字符數組不能保證被正確對齊以讀取爲u_int32的值。

正確的方法做什麼上面的代碼試圖做的是源數組複製到使用memcpy

u_int32 SmartKey::SerialNumber() 
{ 
    unsigned char data[DATA_LENGTH]; 
    u_int32 u; 
    // ... 
    memcpy(&u, data, sizeof u); 
    return u; 
} 

當然,你有一箇中間u_int32值,以確保的字節序數據與平臺上的u_int32對象的字節序相同。

-1

不知道,但我認爲你可以做這樣的:

return (u_int32)&data; 
+0

這會將'data'的地址轉換爲'u_int32'。 OP想要讀取存儲在「數據」的第一個元素中的實際內容。甚至不是同一件事。 – AnT 2010-05-27 17:29:31

0

我覺得這個問題實際上是在你的消隱代碼初始化數據[]結構的地方。我認爲這與你的演員沒有任何關係,這很好。

相關問題