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?
A 1-byte unsigned integer has a range of 0 to 255. Compare this to the 1-byte signed integer range of -128 to 127. Both can store 256 different values, but signed integers use half of their range for negative numbers, whereas unsigned integers can store positive numbers that are twice as large.
The term "unsigned" in computer programming indicates a variable that can hold only positive numbers. The term "signed" in computer code indicates that a variable can hold negative and positive values. The property can be applied to most of the numeric data types including int, char, short and long.
Sure, comparisons between signed and unsigned would be slower, but their result would be more correct in some sense. @Nawaz Your bottom line conclusion is incorrect, unfortunately: if the signed type can contain the unsigned type, the unsigned will be converted to the signed type and not the opposite.
One of the several ways in which 2's complement is convenient, is that C (un)signed conversions don't change the bit pattern. That's particular to 2's complement: the C conversions to unsigned types are defined in terms of modulo arithmetic, not in terms of bit pattern.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With