【问题标题】:Two's complement number representation二进制补码数表示
【发布时间】:2013-07-12 18:17:01
【问题描述】:

我最近一直在为稍作修改的 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 的总和,同时考虑符号位。当我知道铸造应该在大多数情况下起作用时,这似乎有点愚蠢。

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

【问题讨论】:

  • 根据en.cppreference.com/w/cpp/types/integer in c++11保证有符号大小特定整数类型定义的 2s 补码。
  • @BoBTFish,这是我一整天听到的最棒的消息……如果这是真的。但 c++11 草案标准规定:类型 bool、char、char16_t、char32_t、wchar_t 以及有符号和无符号整数类型统称为整数类型。48 整数类型的同义词是整数类型。整数类型的表示应使用纯二进制计数系统来定义值。 49 [示例:本国际标准允许整数类型的 2 的补码、1 的补码和带符号的幅度表示。 —结束示例]
  • 是的,但我确实对c++11 的变化有一些模糊的记忆,所以这就是我去看的原因。我会看看我能在标准中挖掘什么。问题是,这些 typedef 无论如何都不需要存在。
  • 我找到了stackoverflow.com/a/5254075/1171191,但这似乎与c有关。我在c++ 标准中找不到类似的东西。
  • 啊哈!第 18.4.1 节标题&lt;cstdint&gt; 概要,第 2 段“标题定义了与 C 标准中的 7.18 相同的所有函数、类型和宏。”老实说,不确定这是否包括对类型的要求,或者只是 typedef 中类型的实际名称必须与同一平台上的 c 实现相同。 (编辑:那是在 N3337 中,第一稿在 实际 2011 标准之后发布。)

标签: c++ twos-complement


【解决方案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);
}

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

【讨论】:

    猜你喜欢
    • 2021-12-21
    • 2021-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    相关资源
    最近更新 更多