Often an object I use will have (signed) int
parameters (e.g. int iSize
) which eventually store how large something should be. At the same time, I will often initialize them to -1
to signify that the object (etc) hasn't been setup / hasn't been filled / isn't ready for use.
I often end up with the warning comparison between signed and unsigned integer
, when I do something like if( iSize >= someVector.size() ) { ... }
.
Thus, I nominally don't want to be using an unsigned int
. Are there any situations where this will lead to an error or unexpected behavior?
If not: what is the best way to handle this? If I use the compiler flag -Wno-sign-compare
I could (hypothetically) miss a situation in which I should be using an unsigned int
(or something like that). So should I just use a cast when comparing with an unsigned int
--e.g. if( iSize >= (int)someVector.size() ) { ... }
?
A signed integer can store the positive and negative value both but besides it unsigned integer can only store the positive value.
A signed integer is a 32-bit datum that encodes an integer in the range [-2147483648 to 2147483647]. An unsigned integer is a 32-bit datum that encodes a nonnegative integer in the range [0 to 4294967295]. The signed integer is represented in twos complement notation.
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.
According to C language specification, the common part of the range of the corresponding signed and unsigned integer type shall have identical representation (implying, according to the footnote 31, "interchangeability as arguments to functions").
Yes, there are, and very subtle ones. If you are curious, you can check this interesting presentation by Stephan T. Lavavej about arithmetic conversion and a bug in Microsoft's implementation of STL which was caused just by signed vs unsigned comparison.
In general, the problem is due to the fact that because of complement 2 arithmetic, a very small negative integral value has the same bit representation as a very big unsigned integral value (e.g. -1 = 0xFFFF = 65535
).
In the specific case of checking size()
, why not using type size_t
for iSize
in the first place? Unsigned values just give you greater expressivity, use it.
And if you do not want to declare iSize
as size_t
, just make it clear by using an explicit cast that you are aware of the nature of this comparison. The compiler is trying to do you a favor with those warnings and, as you correctly wrote, there might be situations where ignoring them would cause you a very bad headache.
Thus, if iSize
is sometimes negative (and should be evaluated as less than all unsigned int
values of size()
), use the idiom: if ((iSize < 0) || ((unsigned)iSize < somevector.size())) ...
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