如何在 c 中取一个字节的二进制补码?

新手上路,请多包涵

我正在查看一些 C++ 代码,我看到:

  byte b = someByteValue;
 // take twos complement
 byte TwosComplement = -b;

此代码是否采用 b 的二进制补码?如果不是,它在做什么?

原文由 amalgamate 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

stdint.h 定义 uint8_t 的任何实现中, 代码肯定会计算 8 位二进制数的二进制补码:

 #include <stdint.h>
uint8_t twos_complement(uint8_t val)
{
    return -(unsigned int)val;
}

那是因为, 如果 uint8_t 可用,它必须是正好 8 位宽的无符号类型。转换为 unsigned int 是必要的,因为 uint8_t 肯定比 int 窄。如果没有转换,该值将在被否定之前提升为 int ,因此,如果您在非二进制补码机器上,它将不会采用二进制补码。

更一般地说,此代码计算具有 任何 无符号类型的值的二进制补码(使用 C++ 构造进行说明 - 一元减号的行为在两种语言中是相同的,假设没有用户定义的重载):

 #include <cstdint>
#include <type_traits>

template <typename T>
T twos_complement(T val,
                  // "allow this template to be instantiated only for unsigned types"
                  typename std::enable_if<std::is_unsigned<T>::value>::type* = 0)
{
    return -std::uintmax_t(val);
}

因为一元减号被定义为在应用于无符号类型时采用二进制补码。我们仍然需要转换为不小于 int 的无符号类型,但现在我们需要它至少尽可能宽 T ,因此 uintmax_t .

但是,一元减法 不一定 计算类型为 signed 的值的二进制补码,因为 C(和 C++)仍然明确允许基于 使用二进制补码的 CPU 实现有符号量。据我所知,至少有 20 年没有生产过这样的 CPU,所以继续为它们提供供应有点愚蠢,但确实如此。如果你想计算一个值的二进制补码,即使它的类型恰好是有符号的,你必须这样做:(再次使用 C++)

 #include <type_traits>

template <typename T>
T twos_complement(T val)
{
    typedef std::make_unsigned<T>::type U;

    return T(-uintmax_t(U(val)));
}

即转换为相应的无符号类型,然后转换为 uintmax_t然后 应用一元减号,然后反向转换为可能有符号的类型。 (需要强制转换为 U 以确保该值为零而不是从其自然宽度进行符号扩展。)

(但是,如果您发现自己这样做了,请停止并将相关类型更改为无符号。您未来的自己会感谢您。)

原文由 zwol 发布,翻译遵循 CC BY-SA 3.0 许可协议

在二进制补码机器上,否定计算二进制补码,是的。

在 Unisys 上,一些东西,希望现在已经死去并被埋葬(但几年前仍然存在),没有签名类型。

C 和 C++ 支持有符号整数的二进制补码、一个补码和符号和大小表示,并且只有使用二进制补码才能进行二进制补码。


使用 byte 作为无符号类型否定加上转换为 byte 产生二进制补码位模式,无论整数表示如何,因为转换为无符号和无符号算术是模 2 _n_其中 n 是值表示位数。

也就是说,用-x赋值或初始化后的结果是2 n - x,它是x的二进制补码。

这并不意味着否定本身必然计算二进制补码位模式。 To understand this, note that with byte defined as unsigned char , and with sizeof(int) > 1, the byte value is promoted to int 在否定之前,即否定操作是用有符号类型完成的。但是将得到的负值转换为无符号字节,根据定义创建二进制补码位模式以及模算术和转换为无符号类型的 C++ 保证。


2 的补码形式的用处如下 2 n - x = 1 + ((2 n - 1) - x),其中最后一个括号是全一的位模式减去 x ,即 x 的简单按位反转 --- .

原文由 Cheers and hth. - Alf 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题