static_cast<unsigned>(signed)与std::bit_cast<unsigned>(signed)之间有什么区别?

6
再次谈到C++中关于有符号数和无符号数(尺寸相同)之间的转换和强制类型转换。
根据C++标准4.7/2规定:
如果目标类型是无符号的,结果值是源整数对无符号类型表示所用位数2n取模后的最小无符号整数。(注:在二进制补码表示法下,这种转换是概念性的,如果没有截断,则没有位模式变化。)
在二进制补码表示法下,static_cast和std::bit_cast产生相同的位模式。
在一的补码或符号大小表示法下,static_cast(unsigned)(signed)改变位模式是否有理由?
可能是因为“对2^n取模…”(例如unsigned x = -1总是产生111..1位模式),因此static_cast(unsigned)(signed)始终产生二进制补码表示法的位模式吧?

1
bit_cast 仅在 C++20 中可用。而且,在 C++20 中,唯一允许的整数表示是二进制补码。我不明白你的问题“在一的补码或符号大小表示中,为什么 static_cast<unsigned>(signed) 会改变位模式?”。你是在问,为什么标准规定模 2^n 行为?因为在模 2^n 中,非二进制补码数字的位模式可能会发生变化。我认为强制实行模 2^n 行为是有意义的,因为它将在各个平台上保持一致。 - geza
@geza 是的,bit_cast是C++20的特性,但假设它在此之前就已经存在了。问题是:在反码或补码情况下,static_cast<unsigned>(signed)将如何改变位模式,以及为什么? - ilynxy
嗯,这很简单。假设有一个数字-1。在补码中,它的表示形式为1111 1110。如果你将它转换为无符号数,根据模数规则,数值应该变成255。但是255的表示形式是1111 1111。因此,表示形式已经改变了。 - geza
@geza 谢谢!这个正确吗:static_cast<unsigned>(signed) 为任何有符号数产生二进制补码位模式,除了负零(对于非二进制补码表示)? - ilynxy
是的,我认为那是正确的。 - geza
2个回答

0
可能静态转换(带符号)总是产生补码表示的二进制模式,因为它满足"模2^n..."(就像无符号x = -1总是产生111..1的二进制模式)吗?
无符号解释和同样的二进制模式的补码解释在模2^n下是同余的。
所以是的,将负数转换为无符号数总是产生该有符号数的补码表示。如果平台对负数使用补码表示,这是一个空操作;如果它使用其他任何表示,则需要进行转换。

0

使用补码时,你会遇到偏移量为-1的问题:

在一个常数范围内(-1),反码的行为类似于原始数字的负数与二进制加法。然而,与二进制补码不同,由于存在诸如偏移量为-1、取反零会导致不同的负零位模式、算术借位等问题,这些数字并没有得到广泛的使用。

例如,在反码中将“-0”(其具有8位无符号255相同的位模式)转换为static_cast时,根据引用的文本,在转换为无符号数后应该得到“0”。这需要改变位。


如果从有符号的一补数表示中使用 static_cast 转换为无符号类型的 -0 和 +0,将得到相同的位模式(比如零位),那么这是否违反了“与源整数同余”的要求(在这种情况下,将“同余”解释为“双射”或至少是“满射”是否正确)? - ilynxy
@ilynxy: “congruent” 在模运算中有一个特定的技术含义。在解析这个英文句子时,你应该将“congruent modulo 2<sup>n</sup>”视为不可分割的整体。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接