c++ - 为什么 C++ 标准指定在具有混合符号的二进制运算中将有符号整数转换为无符号?

标签 c++ c casting

C和C++标准规定,同阶的有符号整数和无符号整数之间的二元运算,有符号整数被强制转换为无符号整数。由此引起的 SO 有很多问题......我们称之为奇怪的行为:unsigned to signed conversion , C++ Implicit Conversion (Signed + Unsigned) , A warning - comparison between signed and unsigned integer expressions , % (mod) with mixed signedness

但是这些都没有给出任何理由说明为什么标准采用这种方式,而不是强制转换为带符号的整数。我确实找到了一位自称为大师的人,他说这是显而易见的正确做法,但他也没有给出推理:http://embeddedgurus.com/stack-overflow/2009/08/a-tutorial-on-signed-and-unsigned-integers/ .

查看我自己的代码,无论我在哪里组合有符号和无符号整数,我总是需要从无符号转换为有符号。有些地方无关紧要,但我还没有找到一个代码示例可以将有符号整数转换为无符号整数。

在哪些情况下转换为 unsigned 是正确的做法?为什么标准是这样的?

最佳答案

如果无法表示值,则从无符号转换为有符号会导致实现定义的行为。从有符号到无符号的转换总是对无符号位大小的 2 次方取模,因此它始终是明确定义的。

如果每个可能的无符号值都可以用有符号类型表示,则标准转换为有符号类型。否则,选择无符号类型。这保证了转换始终是明确定义的。


注意事项

  1. 如评论中所述,C++ 的转换算法继承自 C 以保持兼容性,这在技术上是 C++ 中如此的原因。

  2. 撰写此说明时,C++ 标准允许三种二进制表示形式,包括符号大小和个的补码。情况已不再如此,并且有充分的理由相信,在合理的熊市 future ,C 也不会出现这种情况。我将脚注留作历史遗迹,但它与当前语言无关。

    有人建议,标准中定义有符号到无符号转换而不是无符号到有符号转换的决定在某种程度上是任意的,而另一个可能的决定是对称的。但是,可能的转换是对称的。

    在标准考虑的两种非 2 的补码表示中,n 位带符号表示只能表示 2n −1 个值,而 n 位无符号表示可以表示 2n 个值。因此,有符号到无符号的转换是无损的并且可以逆转(尽管永远不会产生一个无符号值)。另一方面,无符号到有符号的转换必须将两个不同的无符号值折叠成相同的有符号结果。

    在评论中,公式 sint = uint > sint_max ? uint - uint_max : uint 被提议。这合并了值 uint_max 和 0;两者都映射到 0。即使对于非 2 的补码表示,这也有点奇怪,但对于 2 的补码,这是不必要的,更糟糕​​的是,它需要编译器发出代码来费力地计算这种不必要的混合。相比之下,标准的有符号到无符号转换是无损的,并且在常见情况下(2 的补码架构)它是空操作。

关于c++ - 为什么 C++ 标准指定在具有混合符号的二进制运算中将有符号整数转换为无符号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43336218/

相关文章:

c++ - 在我的项目中添加 sqlite3 库时出现错误消息

c - 如何在浮点支持较差的处理器上计算 GPS 坐标之间的距离?

c - 在抽象语法树 CDT 中包含头文件

java - HoughLinesP 生成空图像

c++ - C++ 中的流使程序崩溃

generics - 我可以使用泛型来利用密封类的优势吗?

python - 在 python 中是否有更快的方法将字符串转换为 float ?

java - 将 LinkedList<Object> 转换为 LinkedList<Customer>

c++ - 如何访问第二个 map 迭代器?

c - 如何检查字符串中是否至少存在三位数字?