Signed/unsigned comparisons

不问归期 提交于 2019-11-26 00:09:48

问题


I\'m trying to understand why the following code doesn\'t issue a warning at the indicated place.

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

I thought it was to do with background promotion, but the last two seem to say otherwise.

To my mind, the first == comparison is just as much a signed/unsigned mismatch as the others?


回答1:


When comparing signed with unsigned, the compiler converts the signed value to unsigned. For equality, this doesn't matter, -1 == (unsigned) -1. For other comparisons it matters, e.g. the following is true: -1 > 2U.

EDIT: References:

5/9: (Expressions)

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:

  • If either operand is of type long double, the other shall be converted to long double.

  • Otherwise, if either operand is double, the other shall be converted to double.

  • Otherwise, if either operand is float, the other shall be converted to float.

  • Otherwise, the integral promotions (4.5) shall be performed on both operands.54)

  • Then, if either operand is unsigned long the other shall be converted to unsigned long.

  • Otherwise, if one operand is a long int and the other unsigned int, then if a long int can represent all the values of an unsigned int, the unsigned int shall be converted to a long int; otherwise both operands shall be converted to unsigned long int.

  • Otherwise, if either operand is long, the other shall be converted to long.

  • Otherwise, if either operand is unsigned, the other shall be converted to unsigned.

4.7/2: (Integral conversions)

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). ]

EDIT2: MSVC warning levels

What is warned about on the different warning levels of MSVC is, of course, choices made by the developers. As I see it, their choices in relation to signed/unsigned equality vs greater/less comparisons make sense, this is entirely subjective of course:

-1 == -1 means the same as -1 == (unsigned) -1 - I find that an intuitive result.

-1 < 2 does not mean the same as -1 < (unsigned) 2 - This is less intuitive at first glance, and IMO deserves an "earlier" warning.




回答2:


Why signed/unsigned warnings are important and programmers must pay heed to them, is demonstrated by the following example.

Guess the output of this code?

#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;
}

Output:

i is greater than j

Surprised? Online Demo : http://www.ideone.com/5iCxY

Bottomline: in comparison, if one operand is unsigned, then the other operand is implicitly converted into unsigned if its type is signed!




回答3:


The == operator just does a bitwise comparison (by simple division to see if it is 0).

The smaller/bigger than comparisons rely much more on the sign of the number.

4 bit Example:

1111 = 15 ? or -1 ?

so if you have 1111 < 0001 ... it's ambiguous...

but if you have 1111 == 1111 ... It's the same thing although you didn't mean it to be.




回答4:


In a system that represents the values using 2-complement (most modern processors) they are equal even in their binary form. This may be why compiler doesn't complain about a == b.

And to me it's strange compiler doesn't warn you on a == ((int)b). I think it should give you an integer truncation warning or something.



来源:https://stackoverflow.com/questions/5416414/signed-unsigned-comparisons

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!