2013-07-12 88 views
4

我最近一直在實施一個專門的解析器,用於稍微修改Abstract Syntax Notation。該規範說整數被編碼爲一個八位字節數組,它被解釋爲二進制二進制補碼整數。二進制補碼錶示

所以,起初我以爲反序列化到一個實際的C++ int這將是簡單地用值0開始,然後像值每個字節的最好辦法OR:

uint64_t value = 0; 
int shift = 0; 
std::vector<uint8_t> octets = { /* some values */ }; 

for (auto it = octets.rbegin(); it != octets.rend(); ++shift, ++it) 
{ 
    value |= uint64_t(*it) << (shift * 8); 
} 

這會離開我用整數存儲在value位模式,我可以那麼解釋爲一個有符號(二進制補碼)鑄造它:

int64_t signed_value = static_cast<int64_t>(value); 

但它發生,我認爲這實在是依靠定義與實現行爲。 C++ doesn't guarantee that signed integers are represented as two's complement。因此,要將編碼整數的實際值作爲C++ int64_t,我需要實際計算位模式中每個第N位的總和2^N,並考慮符號位。當我知道演員應該在大部分時間裏工作的時候,這似乎很愚蠢。

這裏有更好的解決方案,既便攜又高效?

+1

根據「C++ 11」中的http://en.cppreference.com/w/cpp/types/integer,*有保證2s補碼的有符號大小特定的整數typedefs。 – BoBTFish

+0

@BoBTFish,這是我整天聽到的最棒的新聞......如果這是真的。但是C++ 11標準草案說:類型bool,char,char16_t,char32_t,wchar_t,以及有符號和無符號整數類型統稱爲整數類型。整數類型的同義詞是整型。積分類型 的表示應使用純二進制計數系統來定義值.49 [例如:本國際標準 允許對整數類型進行2的補碼,1的補碼和有符號的幅度表示。 -end 例子] – Channel72

+0

是的,但是我對'C++ 11'的改變有些模糊的記憶,所以我就去看了。我會看看我能在標準中挖掘什麼。事情是,這些typedefs並不需要存在。 – BoBTFish

回答

1

如果您的解決方案有效,我認爲您可以使用一些元編程來測試您的平臺是補碼還是補碼。

struct is_ones_complement { 
    static const bool value = ((1 & -1) == 0); 
} 

然後,你可以寫一個可以內聯轉換功能:

template<bool is_ones_complement> 
uint64_t convert_impl(const std::vector<uint8_t>& vec); 

template<> 
uint64_t convert_impl<true>(const std::vector<uint8_t>& vec) { 
    // Your specialization for 1's-complement platforms 
} 

template<> 
uint64_t convert_impl<false>(const std::vector<uint8_t>& vec) { 
    // Your specialization for 2's-complement platforms 
} 

inline uint64_t convert(const std::vector<uint8_t>& vec) { 
    return convert_impl<is_ones_complement::value>(vec); 
} 

未經檢驗的,但它應該工作。