有符号/无符号比较会产生意想不到的结果

Signed/unsigned comparison gives unexpected result

本文关键字:意想不到 结果 符号 无符号 比较      更新时间:2023-10-16

a是有符号整型,包含-100B是无符号整型,包含500

a<b returns FALSE!!

为什么?: P

我可以将b转换为有符号整型并得到正确的结果,但结果却让我大吃一惊,因为我不知道为什么-100<500应该是假的,就像如果编译器自动将a强制转换为无符号类型(这显然不是程序员要求的)。

如果我们保持它们的原样,即第一个符号和第二个符号第二个不签名,那么为什么要一个

这真的很让人困惑。

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

还有什么情况是我必须小心的吗当混合有符号和无符号类型时?

请不要回复明显的"一般用法"不建议使用无符号类型,为什么不坚持呢只有带符号的类型?你会安全得多。"谢谢。

欢呼。

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

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

a=-10010变成11111111111111111111111110011100

b=+50010变成00000000000000000000000111110100

可以看到,当两个数字都被解释为无符号时,a大于b

在混合有符号和无符号类型时,还有其他情况我必须小心吗?

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

为什么不坚持只使用有符号类型呢?

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

在混合有符号和无符号类型时,还有其他情况我必须小心吗?

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

对于复杂表达式,可能会发生许多转换,通常很难确定将发生什么转换。你不应该依赖于你对有些晦涩难懂的规则的知识——清晰比聪明容易,特别是如果代码以后可能由其他人维护的话。

理想情况下,你应该努力在表达式中实现类型一致,如果这是不可能的,你应该确保你的编译器警告级别设置得足够高,以警告不安全的隐式转换,并将所有警告视为错误,并通过适当的强制转换来修复它们。如果编译器不生成此类警告,则可以使用不同的编译器—不一定用于部署,而是作为辅助检查。如果做不到这一点,静态分析工具可能会有所帮助。

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