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?
Yes, the relational operators combined with cast operator. For example:
_Bool TYPE_is_signed = ((TYPE)-1 < 0);
Or as an assertion:
assert((TYPE)-1 < 0); // Require that TYPE is signed
assert((TYPE)-1 > 0); // Require that TYPE is unsigned