If I'm using a library which currently uses a particular numeric type alias, e.g.
typedef uint32_t library_type;
void library_function(library_type x);
How would I ensure that code which needs to pass in a value from a different type remains correct, even if the library changes its typedef?
uint64_t x = get_some_number();
// …need checks here…
library_function((library_type)x);
I could add the following checks:
assert(sizeof library_type >= sizeof uint32_t);
assert(x <= UINT32_MAX);
The second check would ensure the value I get fits within the range of the current library_type
. The library author does not provide a LIBRARY_TYPE_MAX
definition, so the first check tries to guard the second, in case library_type
were to change for whatever reason when the code is compiled in the future.
That first check would catch if library_type
were change to e.g. int8_t
, but what if the library_type
were changed to an int32_t
instead? It's still the right "size" but the range is still less than what I am checking!
Does the C language provide an operator that introspects the signedness of a type, in the same way that sizeof
lets me know the width? Is there any other way to make sure my cast to library_type
will only be reached if it is correct?
std::is_signed
; here I'm wondering if there's anything similar in C (and also whether this is the right approach at all ;-) – Coffeeassert(x <= …)
check would need to be runtime; making sure that check is correct could be compile time or runtime. – Coffee-Wconversion
? Get something like:conversion to uint32_t {aka unsigned int} from int32_t {aka int} may change the sign of the result
– Chaunceychauntuint64_t
(which "probably" doesn't store a big number in practice) to something smaller. – Coffeeuint32_t x_cast = (uint32_t) x; library_function(x_cast);
– ChaunceychauntINTn_MAX
instead ofUINTn_MAX
. – Coffee