Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signed/unsigned comparisons

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?

like image 200
Peter Avatar asked Mar 24 '11 08:03

Peter


People also ask

Can we compare signed and unsigned integer?

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.

What is difference signed and unsigned?

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.

Is it suggested to compare signed and unsigned numbers in C ++?

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.

Can we compare signed and unsigned int in C?

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.


1 Answers

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.

like image 178
Erik Avatar answered Oct 21 '22 13:10

Erik