签名/无符号比较

我试图了解为什么下面的代码不会在指定的地方发出警告。

//from limits.h #define UINT_MAX 0xffffffff /* maximum unsigned int value */ #define INT_MAX 2147483647 /* maximum (signed) int value */ /* = 0x7fffffff */ int a = INT_MAX; //_int64 a = INT_MAX; // makes all warnings go away unsigned int b = UINT_MAX; bool c = false; if(a < b) // warning C4018: '<' : signed/unsigned mismatch c = true; if(a > b) // warning C4018: '<' : signed/unsigned mismatch c = true; if(a <= b) // warning C4018: '<' : signed/unsigned mismatch c = true; if(a >= b) // warning C4018: '<' : signed/unsigned mismatch c = true; if(a == b) // no warning <--- warning expected here c = true; if(((unsigned int)a) == b) // no warning (as expected) c = true; if(a == ((int)b)) // no warning (as expected) c = true; 

我认为这是与背景推广,但最后两个似乎是另有说法。

在我看来,第一个==比较和其他的比较是一样的。

比较带符号和无符号时,编译器将有符号值转换为无符号。 为了平等,这没关系, -1 == (unsigned) -1 。 对于其他比较它很重要,例如以下是真实的: -1 > 2U

编辑:参考文献:

5/9 :(expression式)

许多期望算术或枚举types的操作数的二元运算符以相似的方式导致转换和产生结果types。 目的是产生一个共同的types,这也是结果的types。 这种模式被称为通常的算术转换,其定义如下:

  • 如果任一操作数的types是long double,则另一个应转换为long double。

  • 否则,如果其中一个操作数是双倍的,另一个将被转换为双倍。

  • 否则,如果任一操作数是浮点数,则另一个操作数将被转换为浮点数。

  • 否则,整体促销(4.5)应在两个操作数上执行.54)

  • 然后,如果任一操作数是无符号长整型,另一个将被转换为无符号长整型。

  • 否则,如果一个操作数是一个long int而另一个是unsigned int,那么如果一个long int可以表示一个unsigned int的所有值,那么unsigned int将被转换为一个long int; 否则这两个操作数都将被转换为unsigned long int。

  • 否则,如果其中一个操作数很长,另一个应转换为long。

  • 否则,如果任一操作数是无符号的,则另一个应转换为无符号。

4.7 / 2 :(积分转换)

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

编辑2:MSVC警告级别

当然,MSVC不同警告级别的警告是由开发人员作出的select。 正如我所看到的那样,他们在有符号/无符号平等与大/小比较方面的select是有道理的,当然这完全是主观的:

-1 == -1表示与-1 == (unsigned) -1相同-1 == (unsigned) -1 – 我发现一个直观的结果。

-1 < 2 并不意味着与-1 < (unsigned) 2 – 乍一看,这不太直观,IMO值得“提前”警告。

为什么签名/未签名的警告是重要的,程序员必须注意他们,下面的例子就是certificate。

猜猜这个代码的输出?

 #include <iostream> int main() { int i = -1; unsigned int j = 1; if ( i < j ) std::cout << " i is less than j"; else std::cout << " i is greater than j"; return 0; } 

输出:

 i is greater than j 

惊讶吗? 在线演示: http : //www.ideone.com/5iCxY

底线:相比之下,如果一个操作数是unsigned ,那么另一个操作数如果其types被签名,则隐式转换为unsigned

==运算符只是进行按位比较(通过简单的划分来查看它是否为0)。

小于/大于比较更依赖于数字的符号。

4位例如:

1111 = 15? 或-1?

所以如果你有1111 <0001 …这是不明确的…

但如果你有1111 == 1111 …这是同样的事情,虽然你不是这个意思。

在一个代表使用二进制补码(大多数现代处理器)的系统中,即使是二进制forms,它们也是相等的。 这可能是为什么编译器不会抱怨== b

对我来说,奇怪的编译器不会在==((int)b)上警告你。 我认为它应该给你一个整数截断警告或什么的。