ama*_*ate 6 c++ byte twos-complement
我正在看一些c ++代码,我看到:
byte b = someByteValue;
// take twos complement
byte TwosComplement = -b;
Run Code Online (Sandbox Code Playgroud)
这段代码是否采用b的两个补码?如果没有,它在做什么?
zwo*_*wol 11
在任何stdint.h定义的实现中,此代码肯定会计算8位二进制数的二进制补码uint8_t:
#include <stdint.h>
uint8_t twos_complement(uint8_t val)
{
return -(unsigned int)val;
}
Run Code Online (Sandbox Code Playgroud)
这是因为,如果 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);
}
Run Code Online (Sandbox Code Playgroud)
因为一元减号被定义为在应用于无符号类型时采用二进制补码.我们仍然需要一个无符号类型的强制转换int,但现在我们需要它至少与任何可能的一样宽T,因此uintmax_t.
然而,一元减号也没有必要计算其类型的值的二进制补码签,因为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)));
}
Run Code Online (Sandbox Code Playgroud)
即转换为相应的无符号类型,然后转换为uintmax_t,然后应用一元减号,然后反向转换为可能签名的类型.(对U的强制转换需要确保该值为零,而不是从其自然宽度进行符号扩展.)
(如果你发现自己这样做了,请停止并将有问题的类型改为无符号.未来的自我会感谢你.)
正确的表达式看起来
byte TwosComplement = ~b + 1;
Run Code Online (Sandbox Code Playgroud)
注意:前提是字节iis定义为 unsigned char