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++ 不保证有符号整数表示为二进制补码。因此,要获得编码整数的实际值作为 C++ int64_t,我需要实际计算位模式中每个第 N 位的 2^N 的总和,同时考虑符号位。当我知道铸造应该在大多数情况下工作时,这似乎有点愚蠢。

这里有更好的解决方案,既便携又高效?

4

1 回答 1

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

未经测试,但它应该工作。

于 2013-07-19T08:40:54.240 回答