How portable is casting -1 to an unsigned type?
To be on a "safe" side and do it "right" (C++) way, worth looking at STL:
std::numeric_limits<size_t>::max()
"As I understand it, it works based on the fact that the representation of -1 in twos complement arithmetic is...".
No, it is not based on that fact at all. It is based on the standard requirement, that singed values converted to N-bit unsigned type have to produce an unsigned value, which is "equal" to the original signed one modulo 2^N.
It has to work that way regardless of the signed representation used by the implementation. In case of 2's complement it works that way by itself, but for other representations the compiler will have to do the extra work in order to satisfy the standard requirement.
The requirements on unsigned arithmetic guarantee that casting -1 to an unsigned type will produce the largest number possible for the target type. C99, §6.2.5/9: "...a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type."
This is the same in C and C++ (in the C++ standard, similar wording is found in footnote 41 -- it's not normative, but it's explaining other wording that is).