The other day, I came across this construct:
static_cast<size_type>(-1)
in some example C++ code, which is likely (depending on the details of where size_type
is from) to be equivalent to the following C:
(size_t)(-1)
As I understand it, it works based on the fact that the representation of -1 in twos complement arithmetic is 11111...1
, for as many bits as you have, so this is a quick way of getting the maximum value that an unsigned type like size_t
can hold. However, my understanding is also that C doesn't guarantee that twos complement will be used; if the C implementation uses one's complement, this will be 1 less than the the maximum value, and if it's using signed magnitude, it will be just over half the maximum value.
Is there some wrinkle that I'm missing that insures that this works right regardless of the representation of signed integers being used? Does it differ between C and C++ (many surprising things do)?
As you can see, even assuming the same number of bits used to store an integer, signed and unsigned integers have different positive value limits. Converting a large positive unsigned number to a signed one can lead to bogus results (like negative numbers!) and hard-to-find bugs.
The intptr_t and uintptr_t types are extremely useful for casting pointers when you want to do address arithmetic. They should be used instead of long or unsigned long for this purpose. Use of uintptr_t for casting is usually safer than intptr_t , especially for comparisons.
C and C++ are unusual amongst languages nowadays in making a distinction between signed and unsigned integers. An int is signed by default, meaning it can represent both positive and negative values. An unsigned is an integer that can never be negative.
A signed integer is a 32-bit datum that encodes an integer in the range [-2147483648 to 2147483647].
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).
To be on a "safe" side and do it "right" (C++) way, worth looking at STL:
std::numeric_limits<size_t>::max()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With