No they can’t. Overflows aren’t a real problem. Do not add checked_mul to all your maths.
Thankfully Rust changed overflow behavior from “undefined” to “well defined twos-complement”.
No they can’t. Overflows aren’t a real problem. Do not add checked_mul to all your maths.
Thankfully Rust changed overflow behavior from “undefined” to “well defined twos-complement”.
Having done a bunch of formal verification I can say that overflows are probably the most common type of bug by far.
Arithmetic overflows have become the punchline of video game exploits.
Unsigned underflow is also one of the most dangerous types. You go from one of the smallest values to one of the biggest values.
Don’t do arithmetic with u8 or probably even u16.
If I play "Appeal to Authority" you can read some thoughts on this from Alexandrescu, Stroustrup, and Carruth here: https://stackoverflow.com/questions/18795453/why-prefer-sign...
Unsigned integers are appealing because they make a range of invalid values impossible to represent. That's good! Indices can't be negative so simply do not allow negative values.
The issues are numerous, and benefits are marginal. First and foremost it is extremely common to do offset math on indices whereby negative values are perfectly valid. Given two indices idxA and idxB if you have unsigned indices then one of (idxB - idxA) or (idxA - idxB) will underflow and cause catastrophe. (Unless they're the same, of course).
The benefits are marginal because even though unsigned cannot represent a value below the valid range it can represent a value above container.size() so you still need to bounds check the upper range. If you can't go branchless then who cares about eliminating one branch that can always be treated as cold.
On a modern 64-bit machine doing math on smaller integers isn't any faster and may in fact be slower!
Now it can be valuable to store smaller integers. Especially for things like index lists. But in this case you're probably not doing any math so the overflow/underflow issue is somewhat moot.
Anyhow. Use unsigned when doing bitmasking or bitmanipulation. Otherwise default to signed integer. And default to i64/int64_t. You can use smaller integer types and even unsigned. Just use i64 by default and only use something else if you have a particular reason.
I'm kinda rambling and those thoughts are scattered. Hope it was helpful.