I was looking at this video. Bjarne Stroustrup says that unsigned ints are error prone and lead to bugs. So, you should only use them when you really need t
The problem with unsigned integer types is that depending upon their size they may represent one of two different things:
int
(e.g. uint8
) hold numbers in the range 0..2ⁿ-1, and calculations with them will behave according to the rules of integer arithmetic provided they don't exceed the range of the int
type. Under present rules, if such a calculation exceeds the range of an int
, a compiler is allowed to do anything it likes with the code, even going so far as to negate the laws of time and causality (some compilers will do precisely that!), and even if the result of the calculation would be assigned back to an unsigned type smaller than int
. unsigned int
and larger hold members of the abstract wrapping algebraic ring of integers congruent mod 2ⁿ; this effectively means that if a calculation goes outside the range 0..2ⁿ-1, the system will add or subtract whatever multiple of 2ⁿ would be required to get the value back in range.Consequently, given uint32_t x=1, y=2;
the expression x-y
may have one of two meanings depending upon whether int
is larger than 32 bits.
int
is larger than 32 bits, the expression will subtract the number 2 from the number 1, yielding the number -1. Note that while a variable of type uint32_t
can't hold the value -1 regardless of the size of int
, and storing either -1 would cause such a variable to hold 0xFFFFFFFF, but unless or until the value is coerced to an unsigned type it will behave like the signed quantity -1.int
is 32 bits or smaller, the expression will yield a uint32_t
value which, when added to the uint32_t
value 2, will yield the uint32_t
value 1 (i.e. the uint32_t
value 0xFFFFFFFF).IMHO, this problem could be solved cleanly if C and C++ were to define new unsigned types [e.g. unum32_t and uwrap32_t] such that a unum32_t
would always behave as a number, regardless of the size of int
(possibly requiring the right-hand operation of a subtraction or unary minus to be promoted to the next larger signed type if int
is 32 bits or smaller), while a wrap32_t
would always behave as a member of an algebraic ring (blocking promotions even if int
were larger than 32 bits). In the absence of such types, however, it's often impossible to write code which is both portable and clean, since portable code will often require type coercions all over the place.