Although I deeply sympathize with Chris' line of reasoning, I do not agree here (at least in part, I play the devil's advocate). There is nothing wrong with using unsigned types for sizes, and this can even be useful in some circumstances.
Chris justifies types with a size sign that they are naturally used as array indices, and you might want to do arithmetic with array indices, and this arithmetic can create temporary values that are negative.
This subtle and unsigned arithmetic does not cause problems, provided that you will correctly interpret your values when performing comparisons. Since the behavior of the overflow of unsigned integers is completely defined, temporary overflows in the negative range (or in huge positive numbers) do not introduce any errors if they are corrected before performing the comparison.
Sometimes overflow behavior is even desirable, since unsigned arithmetic overflow behavior makes certain range checks expressible as one comparison, which would otherwise require two comparisons. If I want to check if x in the range [a,b] and all unsigned values, I can simply do:
if (x - a < b - a) { }
This does not work with signed variables; such range checks are fairly common for array sizes and offsets.
I mentioned earlier that the benefit is that overflow arithmetic has certain results. If your index arithmetic overflows the signed type, the behavior is determined by the implementation; There is no way to make your program portable. Use an unsigned type and this problem will disappear. Admittedly, this applies only to huge offsets, but this applies to some applications.
In general, objections to unsigned types are often overestimated. The real problem is that most programmers do not really think about the exact semantics of the code they write, and for small integer values, signed types behave more in accordance with their intuition. However, data sizes are growing pretty fast. When we deal with buffers or databases, we often go beyond the "small" range, and signed overflows are much more problematic for proper handling than unsigned overflows. The solution is not to “not use unsigned types,” but to “think carefully about the code you write and make sure you understand it.”
Stephen canon
source share