3 ms·
Reposting a comment of mine from another thread (https://news.ycombinator.com/item?id=29770689 https://news.ycombinator.com/item?id=29770689): For me, the main
by cesarb 4y ago
Reposting a comment of mine from another thread (https://news.ycombinator.com/item?id=29770689 https://news.ycombinator.com/item?id=29770689):
For me, the main reason to prefer unsigned integers whenever possible is: less special cases.
When a signed integer is used as an array index, the value can be in one of three ranges: the <0 range, the >=0 && <size range, and the >=size range. To validate the index, you need two comparisons. When an unsigned integer is used as an array index, there are only two ranges: the <size range, and the >=size range, and you need only a single comparison.
And that's not the worst situation with signed integers. From a more general point of view, there are four "classes" of signed integer: positive (>0), zero, negative (<0), and INT_MIN. Everybody tends to forget about that last one, but it's "special" in that it can break things in unexpected ways. Negating it doesn't work (you'd expect negating any number less than zero to result in a number greater than zero, but for INT_MIN that doesn't happen). Dividing it can trap (see for instance https://kqueue.org/blog/2012/12/31/idiv-dos/ https://kqueue.org/blog/2012/12/31/idiv-dos/ which has a couple of examples) or worse.
With unsigned integers, there are only two "classes", zero and non-zero, and it's common to not even need special treatment for zero, reducing the whole thing to a single "class" of values.
- jcelerier 4y ago> When a signed integer is used as an array index, the value can be in one of three ranges: the <0 range, the >=0 && <size range, and the >=size range. To validate the index, you need two comparisons. When an unsigned integer is used as an array index, there are only two ranges: the <size range, and the >=size range, and you need only a single comparison. but the need for the <= 0 case does not disappear - it's a property of integers (Z) whether you want it or not, and the very second you do an arithmetic operation such as a - b, you expect this to behave like numbers: void compute(int* array, size_t len, /* any integral type */ x) { size_t res = len - x; if(res < len) printf("%d", array[res]) } this code is wrong an awful lot of time because there isn't actually "a single range" just because the integer is unsigned - you have to make sure that `len >= x` if you want a correct result so there will be comparisons there instead, but those are much trickier to get right from my experience finding bugs in such code. and if you are going to say that "this rarely happens" - here is an excerpt of a set of simple cases I could find just by grepping on the projects I have cloned where using unsigned will cause crashes: https://pastebin.com/sTgGPV9k https://pastebin.com/sTgGPV9k