Presentation of two additions

I recently implemented a specialized parser for a slightly modified Abstract syntactic notation . The specification says that integers are encoded as an array of octets, which should be interpreted as a binary integer with two additions.

So, at first I thought that the best way to non-esterize this into a real C ++ int is to just start with a value of 0, and then OR each octet with a value like:

 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); } 

This would leave me with a bit pattern stored in value , which I could then interpret as a signed integer (2'-complement), producing it:

 int64_t signed_value = static_cast<int64_t>(value); 

But it occurred to me that this really depends on the behavior defined by the implementation. C ++ does not guarantee that signed integers are represented as two additions . So, in order to get the actual value of the encoded integer as C ++ int64_t , I would need to actually calculate the sum of 2 ^ N for each Nth bit in the bit scheme, taking into account the sign bit. It seems silly when I know that casting should just work most of the time.

Is there a better solution here that will be both portable and efficient?

+4
source share
1 answer

If your solution works, I think you can use a little metaprogramming to check if your platform is one add-on or two add-ons.

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

And then you can write a built-in conversion function:

 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); } 

Unconfirmed, but it should work.

+1
source

Source: https://habr.com/ru/post/1491162/


All Articles