有符号/无符号比较会产生意外结果

时间:2014-05-02 15:54:39

标签: c++ c visual-c++

a是一个带符号的int,包含-100 b是unsigned int,包含500

a<b returns FALSE!!

为什么到地球? :P

我可以将b转换为signed int并获得正确的结果, 但是离开了,而结果让我感到惊讶, 因为我不知道为什么-100 <500应该是假的,它就像 如果编译器自动将a转换为无符号类型 (这显然不是程序员要求的。)

如果我们保持原样,即第一次签名和 第二个未签名,那么为什么要一个

这真的很混乱。

现在我必须纠正我的所有代码,寻找 有符号和无符号整数之间的比较,以及强制转换 这两个变量都是我所说的类型。 : - /

还有其他任何情况我都要小心 混合有符号和无符号类型时?

请不要回复显而易见的&#34;一般使用 未签名的类型是不可取的,为什么不坚持 只有签名类型?你会更加安全&#34;。感谢。

干杯。

2 个答案:

答案 0 :(得分:9)

根据整数提升的规则,当您对具有相同位数的有符号和无符号数执行操作时,有符号数将转换为无符号。

看一下这两个数字的二进制表示。当a被重新解释为无符号时,它变为4294967196 10

a = -100 10 变为11111111111111111111111110011100

b = + 500 10 变为00000000000000000000000111110100

如您所见,当a两个数字都被解释为无符号时,b大于{{1}}。

  

在混合有符号和无符号类型时,还有其他任何情况需要注意吗?

这个问题的答案是响亮的“是” - 当你混合有符号和无符号类型时,你应该非常小心。这就是为什么当有符号和无符号类型混合在同一表达式中时,C ++编译器会发出警告的原因。解决所有这些警告很重要,主要是因为它可以帮助您了解自己的程序。

  

为什么不坚持只使用签名类型?

这不是一个好建议 - 你想要未签名类型的情况,因为你的程序模型不能为负的现实项目,或者因为你的能力使用整数类型存储位模式 - 例如,表示小集的子集。无符号类型本身对您的程序来说并不坏,只要您避免将它们与负数混合,或者在需要进行混合时提供显式强制转换。

答案 1 :(得分:0)

  

在混合有符号和无符号类型时,还有其他任何情况需要注意吗?

是的,有很多情况。必须通过转换为某种常见类型来解析涉及混合数据类型的任何二元运算符表达式。如果未提供显式转换,则编译器将根据语言规则提供隐式转换。

对于复杂的表达式,可能会发生许多转换,并且通常很难确定会发生什么。你不应该依赖于你对某些神秘规则的了解 - 它更容易清晰而不是聪明,特别是如果代码以后可能由其他人维护。

理想情况下,您应该在表达式中争取类型协议,在这种情况下,您应该确保将编译器警告级别设置得足够高以警告不安全的隐式转换,并将所有警告视为错误并通过修复它们。适当的演员。如果编译器没有生成此类警告,则可能使用不同的编译器 - 不一定用于部署,而是用作辅助检查。如果没有静态分析工具可能会有所帮助。

一般情况下,您可以通过对所有整数算术数据类型(即将对其执行算术的数字)使用普通int来避免大多数问题。即使该值永远不应为负数,只要int的正范围足够,最好使用它来避免算术运算中的隐式转换。