没有兼容的方式来转换相同大小的有符号/无符号

我担心我可能会丢失一些微不足道的东西,但是如果您希望保留原始的无符号值,似乎没有实际的安全方式来转换为签名类型或从其转换。

在reinterpret_cast上,5.2.10没有列出一个整数到整数转换,因此它没有被定义(并且static_cast没有定义额外的转换)。 关于积分转换4.7.3基本上说大的无符号转换将被实现定义(因此不可移植)。

这似乎是有限制的,因为我们知道,例如,在任何硬件上, uint64_t应该可以安全地转换为int64_t并且不会改变值。 再加上关于标准布局类型的规则实际上保证了安全转换,如果我们在这两种类型之间进行memcpy而不是赋值。

我对么? 有没有一个合法的理由,为什么不能在整数类型之间进行reinterpret_cast足够的大小?


澄清:绝对无符号的签名版本不保证一个值,但它只是我正在考虑的往返行程(无符号=>有符号=>无符号)


更新 :仔细查看答案并交叉检查标准,我相信memcpy实际上并不能保证能够正常工作,因为它没有声明这两种类型是布局兼容的,并且都不是char类型。 进一步更新,挖掘到C标准这个memcpy应该工作,因为目标的大小足够大,它复制字节。


解答 :为什么不允许reinterpret_cast执行此转换,似乎没有技术原因。 对于这些固定大小的整数类型, memcpy可以保证正常工作,事实上,只要中间体可以表示所有的位模式,就可以使用任何中间类型(由于可能存在陷阱模式,float可能很危险)。 一般来说,你不能在任何标准布局类型之间使用memcpy,它们必须是兼容的或char类型的。 这里的整数是特殊的,因为它们有额外的保证。


正如你指出的那样,memcpy是安全的:

uint64_t a = 1ull<<63;
int64_t b;
memcpy(&b,&a,sizeof a);

值b仍然是实现定义的,因为C ++不需要二进制补码表示,但将其转换回来会给出原始值。

正如Bo Persson指出int64_t将是二进制补码。 因此,memcpy应该产生一个带符号的值,其中简单的整数转换返回到无符号类型被很好地定义为原始的无符号值。

uint64_t c = b;
assert( a == c );

另外,你可以实现你自己的'signed_cast'来简化转换(我不会利用这两个补充的东西,因为它们不限于intN_t类型):

template<typename T>
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value,T>::type
signed_cast(typename std::make_unsigned<T>::type v) {
    T s;
    std::memcpy(&s,&v,sizeof v);
    return s;
}

template<typename T>
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value,T>::type
signed_cast(typename std::make_signed<T>::type v) {
    T s;
    std::memcpy(&s,&v,sizeof v);
    return s;
}

我们知道你不能将任意位序列转换为浮点,因为它可能是陷阱表示。

是否有任何规则表明在有符号整型中不能有陷印表示? (无符号类型不能,因为范围被定义的方式,所有表示都需要有效的值)

签名表示还可以包括等价类(例如+0 == -0 ),并且可以将这样的类中的值强制为规范表示形式,从而打破往返。

以下是标准中的相关规则(sectin 4.7, [conv.integral] ):

如果目标类型是无符号的,则结果值是与源整数相同的最小无符号整数(模2n,其中n是用于表示无符号类型的位数)。 [注:在二进制补码表示中,这种转换是概念性的,并且位模式没有变化(如果没有截断)。 - 结束注释]

如果目标类型是带符号的,如果它可以用目标类型(和位域宽度)表示,则该值不变。 否则,该值是实现定义的。

如果您的意思是在指针或引用上使用reinterpret_cast而不是值,则必须处理strict-aliasing规则。 你发现这种情况是明确允许的


据推测,这是不允许的,因为对于具有符号幅度表示的机器来说,它违反了将0映射为无符号0的最小惊喜原则,而有符号-0映射到其他(可能非常大)的数字。

考虑到memcpy解决方案的存在,我认为标准组织决定不支持这种不直观的映射,可能是因为unsigned-> signed-> unsigned不如指针 - >整数 - >指针那么有用。

链接地址: http://www.djcxy.com/p/57777.html

上一篇: No compliant way to convert signed/unsigned of same size

下一篇: Identifying subject/domain of a given word