Comparison between signed and unsigned integer expressions
source link: https://peter.bourgon.org/blog/2009/05/01/comparison-between-signed-and-unsigned-integer-expressions.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Comparison between signed and unsigned integer expressions
2009 05 01
Many times I find myself comparing size_t
with int
; for example, when I need
to check that a vector isn’t bigger than some runtime-determined boundary value.
Using -Wall
(as everyone should be), and assuming your size_t
is defined
rationally, compilers correctly flag this as problematic:
./test.cpp: In function main:
./test.cpp:8: warning: comparison between signed and unsigned integer expressions
I think the best solution is to static_cast
one to the other. But which to
which? If you cast the int
to a size_t
, you run the risk of a negative int
overflowing into an incorrectly-huge size_t
. And if you cast the size_t
to
an int, you run the risk of a huge size_t
overflowing into an incorrectly-
negative int. So, pragmatically, if your int
has a high likelihood of being
negative, you should cast your size_t
to an int
; if your size_t
has a high
likelihood of being larger than your implementation’s max int
value, you
should cast your int
to a size_t
.
Yet, at a high level, size_t
is a “concept” both in the sense that it is not
directly a primitive type, and that it represents something not immediately
mathematical: it’s a non-negative count of a number of items. That, handily,
maps to an unsigned something int
in C++, as an implementation detail. So one
could argue that the best bet is to cast the int
to a size_t
, as it’s
casting a lower-order concept to a higher one, which (presumably) is capable of
handling it.
But an int
is also a sort of “concept”, albeit a mathematical one directly
supported by most modern languages. It’s an integer value that may by definition
be negative; any limitation on the size of that value is an implementation
detail. In other words, by definition and ignoring implementation details, a
size_t is-a int
, whereas an int
is-NOT-a size_t
. And therefore, I think in
the general case you should compare int
s and size_t
s by casting the size_t
to an int
, eg.
int max_size = ...;
if (static_cast<int>(my_vector.size()) > max_size)
{
// handle error
}
Luckily this also tends to be the correct pragmatic choice; if your STL containers regularly contain more than N-million elements, you are probably not very interested in bounds-checking them.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK