2014-05-09 87 views
2

我有以下功能:C++ - 警告:右移位計數型的> =寬度32位計算機上

void func(unsigned long v) 
{ 
    char max_byte = 0xFF; 
    char buffer[8]; 

    buffer[0] = static_cast<char>((v)  & max_byte); 
    buffer[1] = static_cast<char>((v >> 8) & max_byte); 
    buffer[2] = static_cast<char>((v >> 16) & max_byte); 
    buffer[3] = static_cast<char>((v >> 24) & max_byte); 
    buffer[4] = static_cast<char>((v >> 32) & max_byte); 
    buffer[5] = static_cast<char>((v >> 40) & max_byte); 
    buffer[6] = static_cast<char>((v >> 48) & max_byte); 
    buffer[7] = static_cast<char>((v >> 56) & max_byte); 
} 

它接受一個unsigned long參數,並插入其8個字節到char緩衝液(不嘗試找出原因,這是一個有意義功能的簡潔版本)。

此代碼編譯以及在64位,但在32位,我得到以下警告:

warning: right shift count >= width of type 

參考線:

buffer[4] = static_cast<char>((v >> 32) & max_byte); 
    buffer[5] = static_cast<char>((v >> 40) & max_byte); 
    buffer[6] = static_cast<char>((v >> 48) & max_byte); 
    buffer[7] = static_cast<char>((v >> 56) & max_byte); 

我想我明白了警告,但我不當然我該怎麼做才能在32位上順利編譯它。

+4

是的,它是[未定義的行爲](http://stackoverflow.com/questions/18918256/is-right-shift-undefined-behavior-if-the-count-is-larger-than-the -width-of-the-t/18918340#18918340)執行寬度大於或等於位數的移位。 –

+0

32位系統上'unsigned long'的長度是多少? – Codor

+0

@ShafikYaghmour我明白,但解決方案是什麼。 'unsigned long'的長度是64位,我需要正確處理它。 – idanshmu

回答

5

unsigned long只保證有32位。請參閱here。您需要使用unsigned long long來保證64位。

更妙的是使用fixed width integer,即uint64_t。它們在標頭<cstdint>(或<stdint.h>)中定義。

+0

「也在早期版本的C++中」 - 只有在庫/編譯器具有非標準擴展時。在C++ 11之前它們不是標準的。 –

8

使用fixed-width integer types。在這種情況下,您需要std::uint64_t

+1

或至少*嘗試*,沒有要求提供那些實施:)但是,這是解決方案。 –

2

當編寫依賴於整數大小的代碼,你真的需要使用<stdint.h>

#include <stdint.h> 

void func(uint64_t v) 
{ 
    static const uint8_t max_byte = 0xFF; // Let the compiler hardcode this constant. 
    uint8_t buffer[8]; 

    buffer[0] = static_cast<uint8_t>((v)  & max_byte); 
    buffer[1] = static_cast<uint8_t>((v >> 8) & max_byte); 
    buffer[2] = static_cast<uint8_t>((v >> 16) & max_byte); 
    buffer[3] = static_cast<uint8_t>((v >> 24) & max_byte); 
    buffer[4] = static_cast<uint8_t>((v >> 32) & max_byte); 
    buffer[5] = static_cast<uint8_t>((v >> 40) & max_byte); 
    buffer[6] = static_cast<uint8_t>((v >> 48) & max_byte); 
    buffer[7] = static_cast<uint8_t>((v >> 56) & max_byte); 
} 
+0

今天不是我的一天。調制解調器丟失連接權,因爲我正在嘗試發佈。 > _ < –

0

我可能是錯的假設是沒有答案的真正獲取到這個問題的要點,因此在這裏不用。

編譯爲一個64位的二進制長被定義爲一個64位的值(或8個字節),而32位二進制長是相同的一個int是32位或4個字節。

該問題有幾種解決方案:
1.重新定義參數爲long long或int64,如其他響應中所建議的。
2.添加一個預處理器定義來阻擋違規位操作。如...

#ifdef __LP64__ 
buffer[4] = static_cast<uint8_t>((v >> 32) & max_byte); 
buffer[5] = static_cast<uint8_t>((v >> 40) & max_byte); 
buffer[6] = static_cast<uint8_t>((v >> 48) & max_byte); 
buffer[7] = static_cast<uint8_t>((v >> 56) & max_byte); 
#endif 


這將確保長根據處理器體系結構,而不是迫使長永遠是64位的處理。
3.使用聯合將達到相同的最終結果也爲提供

void func(unsigned long v) 
{ 
    union { 
     unsigned long long ival; 
     unsigned char  cval[8]; 
    } a; 

    a.ival = v; 
} 
當然

如果使用C++,那麼您可以通過修改以上如下存儲在一個類似的方式的任何基本數據類型的代碼:

template<class I> 
void func(I v) { 
    union { 
     unsigned long long ival; 
     unsigned char  cval[8]; 
     I     val; 
    } a; 

    a.val = v; 
}