2016-01-22 243 views
4

我試圖將4個字節轉換爲使用C++的整數。使用C++將四個字節轉換爲整數

這是我的代碼:

int buffToInteger(char * buffer) 
{ 
    int a = (int)(buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]); 
    return a; 
} 

上面的代碼工作在幾乎所有情況下,例如: 當我的緩衝區:"[\x00, \x00, \x40, \x00]"的代碼將返回16384預期。

但是,當緩衝區填充:"[\x00, \x00, \x3e, \xe3]"時,代碼將無法按預期方式工作,並將返回"ffffffe1"

有誰知道爲什麼會發生這種情況?

+3

「..代碼將無法按預期工作」:您的代碼*不會按預期工作(因爲我期望這種行爲有符號的字節值)。 – usr2564301

+0

@Jongware爲什麼它返回ffffffe1而不是16102?你能解釋一下嗎? –

+0

@ i486問題不在endians中。 – SashaMN

回答

12

您的buffer包含有符號個字符。所以,實際上,buffer[0] == -29,其在轉換爲int時得到符號擴展爲0xffffffe3,並且依次爲(0x3e << 8) | 0xffffffe3 == 0xffffffe3

您需要確保您的個人buffer字節解釋unsigned,要麼通過聲明buffer作爲unsigned char *,或通過顯式鑄造:

int a = int((unsigned char)(buffer[0]) << 24 | 
      (unsigned char)(buffer[1]) << 16 | 
      (unsigned char)(buffer[2]) << 8 | 
      (unsigned char)(buffer[3])); 
4

在表達式buffer[0] << 24中,值24是int,因此buffer[0]也將在執行轉換之前轉換爲int

在您的系統上,一個char顯然是帶符號的,並且在轉換爲int時會被標記爲擴展名。

1

有一個內隱晉升爲您的輪班一個符號整型。 這是因爲字符(顯然)是在您的平臺上簽名的(常見的事情),並且隱式地提升爲整數。事實上,這一切都不會發揮作用,否則因爲< < 8(及更高版本)將擦洗所有的位!

如果你堅持使用簽署字符的緩衝區這會給你想要的東西:

#include <iostream> 
#include <iomanip> 

int buffToInteger(char * buffer) 
{ 
    int a = static_cast<int>(static_cast<unsigned char>(buffer[0]) << 24 | 
     static_cast<unsigned char>(buffer[1]) << 16 | 
     static_cast<unsigned char>(buffer[2]) << 8 | 
     static_cast<unsigned char>(buffer[3])); 
    return a; 
} 

int main(void) { 
    char buff[4]={0x0,0x0,0x3e,static_cast<char>(0xe3)}; 
    int a=buffToInteger(buff); 

    std::cout<<std::hex<<a<<std::endl; 

    // your code goes here 
    return 0; 
} 

要小心一點移簽署價值。促銷活動不只是添加字節,還可能會轉換價值。

例如,這裏的一個問題是,您不能直接使用static_cast<unsigned int>(buffer[1])(etc.),因爲它將signed char值轉換爲signed int值,然後將該值重新解釋爲無符號值。

如果有人問我所有的隱式數值轉換是不好的。沒有任何計劃應該有這麼多,他們會變成一件苦差事。這是從C繼承的C++中的一種柔和,會導致遠遠超過其價值的各種問題。 它在C++中更糟糕,因爲它們使已經令人困惑的重載規則更加混亂。