c++ - comparison between signed and unsigned integer expressions




签名/未签名比较 (3)

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

//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;

我认为这与背景推广有关,但最后两个似乎不这么说。

在我看来,第一次==比较与其他人的签名/未签名不匹配一样多吗?


==运算符只是进行逐位比较(通过简单除法来查看它是否为0)。

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

4位示例:

1111 = 15? 还是-1?

所以,如果你有1111 <0001 ......它的含糊不清......

但如果你有1111 == 1111 ......虽然你不是故意的,但它是一样的。


为什么签名/未签名警告很重要,程序员必须注意它们,以下示例说明了这一点。

猜猜这段代码的输出?

#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/5iCxYhttp://www.ideone.com/5iCxY

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


将signed with signed与unsigned进行比较时,编译器会将signed值转换为unsigned。 对于相等,这无关紧要, -1 == (unsigned) -1 。 对于其他比较,它很重要,例如以下情况: -1 > 2U

编辑:参考文献:

5/9 :(表达式)

许多期望算术或枚举类型的操作数的二元运算符会以类似的方式引起转换并产生结果类型。 目的是产生一个通用类型,它也是结果的类型。 此模式称为通常的算术转换,其定义如下:

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

  • 否则,如果任一操作数为double,则另一个操作数应转换为double。

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

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

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

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

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

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

4.7 / 2 :(整体转换)

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

EDIT2:MSVC警告级别

关于MSVC的不同警告级别的警告当然是开发人员做出的选择。 正如我所看到的,他们在签名/无符号平等与更大/更少比较相关的选择是有道理的,当然这完全是主观的:

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

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





signed