uintptr_t uint_to_uintptr(unsigned int n) {
return (uintptr_t)n;
}
uintptr_t ulint_to_uintptr(unsigned long int n) {
return (uintptr_t)n;
}
uintptr_t ullint_to_uintptr(unsigned long long int n) {
return (uintptr_t)n;
}
Which of the 3 casts above does not cause a loss of information (bits)?
The c99 standard says:
The following type designates an unsigned integer type with the property that any valid pointer to
void
can be converted to this type, then converted back to pointer tovoid
, and the result will compare equal to the original pointer:uintptr_t
but it does not specify what the size of this unsigned integer type
is.
Does it mean the maximum value of greatest-width unsigned integer type (UINTMAX_MAX
) or a simple unsigned int
?
About the widths1 and representation capabilities of these types and the relations between them, the C 2018 standard specifies each type can represent at least the value shown here:
Type | Value | Source in Standard |
---|---|---|
unsigned int |
65,535 | 5.2.4.2.1 1 |
unsigned long int |
4,294,967,295 | 5.2.4.2.1 1 |
unsigned long long int |
18,446,744,073,709,551,615 | 5.2.4.2.1 1 |
uintptr_t |
65,535 | 7.20.2.4 1 |
and it specifies these additional requirements:
unsigned long int
is at least as wide as unsigned int
(6.3.1.1 1, as a consequence of rank properties).
unsigned long long int
is at least as wide as unsigned int
and unsigned long long int
(6.3.1.1 1, as a consequence of rank properties).
uintptr_t
can, in some fashion, represent any valid void *
(7.20.1.4 1).
As we can see from these, there is no limit on how big any of the types unsigned int
, unsigned long int
, or unsigned long long int
can be, and no rule prevents any of them from being wider or narrower than uintptr_t
. Therefore, there is no guarantee in the C standard that converting an unsigned int
, unsigned long int
, or unsigned long long int
to uintptr_t
will not lose information.
1 The width of an integer type is the number of bits used to represent its value, including a sign bit if any. The precision is the number of bits used to represent its value excluding any sign bit. For an unsigned type, the width and the precision are the same.