0

a is a signed int and contains -100 b is an unsigned int and contains 500

a<b returns FALSE!!

Why on earth? :P

I can cast b to signed int and get the correct results, but leaving as is instead the result surprises me a lot, as I have no idea why -100<500 should be false, it's like if the compiler casts a to an unsigned type automatically (and this was clearly not requested by the programmer).

If we keep them as they are, i.e. the first signed and the second unsigned, then why should a

This is very confusing really.

Now I have to correct all of my code, looking for comparisons between signed and unsigned ints, and cast both variables to the type I mean. :-/

Is there any other situation I have to be careful about when mixing signed and unsigned types?

Please do not reply the obvious "generically the use of unsigned types is not adviceable, why don't you stick with only signed types? you will be much safer". THANKS.

Cheers.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • How about you also show all the relevant code? – OldProgrammer May 02 '14 at 15:57
  • 1
    What's better: converting signed to unsigned and having `a – zneak May 02 '14 at 15:57
  • 2
    With the right warning levels you should receive a warning for this kind of code. Something like `implicit conversion changes signedness: 'int' to 'unsigned long'`. – Shafik Yaghmour May 02 '14 at 15:59
  • `Now I have to correct all of my code, looking for comparisons between signed and unsigned ints, and cast both variables to the type I mean.` Didn't the compiler generate a warning that you were mixing signed and unsigned ints in the expression? – PaulMcKenzie May 02 '14 at 15:59
  • 1
    "it's like if the compiler casts a to an unsigned type automatically". Yep. Google for "C Usual arithmetic conversions". – Mark Dickinson May 02 '14 at 16:00
  • Although the reason behind the behavior shown in this post and that in the alleged duplicate are the same, the symptoms observed differ significantly. Voting to re-open. – Sergey Kalinichenko May 02 '14 at 17:11

2 Answers2

9

According to the rules of integral promotions, when you perform an operation on a signed and an unsigned number with the same number of bits, the signed number is converted to unsigned.

Take a look at the binary representation of the two numbers. When a is re-interpreted as unsigned, it becomes 429496719610:

a=-10010 becomes 11111111111111111111111110011100

b=+50010 becomes 00000000000000000000000111110100

As you can see, a is greater than b when both numbers are interpreted as unsigned.

Is there any other situation I have to be careful about when mixing signed and unsigned types?

The answer to this question is a resounding "Yes" - you should be extremely careful when you mix signed and unsigned types. This is the reason why C++ compilers issue warnings when signed and unsigned types are mixed in the same expression. Addressing all these warnings is important, primarily because it helps you understand your own program.

why don't you stick with only signed types?

This is not a good advise - the are situations when you want unsigned types, because the real-life items that your program model cannot be negative, or because you use an integral type for its ability to store bit patterns - for example, to represent a subset of a small set. Unsigned types by themselves are not bad for your program, as long as you avoid mixing them with negative numbers, or provide explicit casts whenever such mixing need to occur.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

Is there any other situation I have to be careful about when mixing signed and unsigned types?

Yes there are a number of situations. Any binary operator expression involving mixed data types must be resolved by conversion to some common type. If no explicit conversion is provided, the compiler will supply an implicit conversion according to the rules of the language.

For complex expressions a number of conversions may occur, and it is often difficult to be sure what will happen. You should not rely on your knowledge of the somewhat arcane rules - its easier to be clear than clever, especially if the code may later be maintained by someone else.

Ideally you should strive for type agreement in expressions, where that is not possible you should ensure that your compiler warning level is set sufficiently high to warn of unsafe implicit conversions and to regard all warnings as errors and fix them by appropriate casts. If you compiler does not generate such warnings, you might use a different compiler - not necessarily for deployment, but as a secondary check. Failing that a static analysis tool may help.

In general you can avoid most issues by preferring the use of plain int for all integer arithmetic data types (i.e. numbers you will perform arithmetic on). Even if the value should never be negative, so long as the positive range of int is sufficient it is better to use that to avoid implicit conversions in arithmetic operations.

Clifford
  • 88,407
  • 13
  • 85
  • 165