Reputation:
When comparing an int
to an unsigned int
, for example:
signed int si = -1;
unsigned int ui = 0;
if (ui > si)
{
// Do something
}
si
will be converted to an unsigned int
and so it will be bigger than ui
. So why is this even allowed if the result will not be as expected, is it made this way for historical reasons, and if they had to do it again they wouldn't allow it?
Upvotes: 2
Views: 817
Reputation: 31
There are only two choices for the language:
As dasblinkenlight says, the language mandates the former. The reason is that it makes the code simpler. In modern machines, the top bit is the sign bit, and the hardware can perform either a signed or an unsigned comparison, so the code is just a compare followed by an unsigned conditional jump.
To treat the unsigned as signed, the compiler could throw away (mask out) the top bit in the unsigned word ui and then perform a signed test, but that would change its value. Alternatively it could test the top bit of ui first and return greater if set, then perform the masking above.
Bottom line, the language choice was made because it's more code-efficient.
Upvotes: 0
Reputation: 141544
This rule exists because it is the best solution to the problem.
You can't compare apples and oranges. The only options are:
Out of the first two options, converting both to unsigned makes more sense than converting both to signed.
How about the third option? I suppose a possibility would be to convert both values to long
and then do the comparison. This might seem like a good idea at first, but if you think about it some more then there are some problems:
long
and int
are the same size then this doesn't actually helplong
is bigger than int
, you have just moved the problem off to the case of comparing a long
with an unsigned long
.The last point is important. The historical rules about short
and char
being promoted to int
are actually extremely annoying when you are writing template code or code with overloaded functions, because it changes which overload is called.
We would not want to introduce any more rules of the same type (e.g. promote int
to long
if it is in comparison with unsigned int
but only if sizeof(long)
> sizeof(int)
yada yada yada).
Upvotes: 2
Reputation: 23600
The reason is mostly historical. C++ is big on being compatible with C code even today. You can take a C code-base and convert it verbatim to C++ and it will probably work, even though there are some minor differences and incompatibilities. C has defined it that way and C++ will not change it, because otherwise it would change the meaning of code and therefore break programs that would otherwise work.
In the current working draft (N4296) you can find the rules in section 5.10.5.
Upvotes: 1
Reputation: 726479
C++ has the following rules for deciding the type to which the two values are converted after integer promotions have been done (chapter 5, clause 9):
- If both operands have the same type, no further conversion is needed.
- Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank.
- Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.
- Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.
- Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.
The last rule applies here, because both int
and unsigned int
have the same rank.
Upvotes: 5