typedef
was a signed or unsigned integral type (e.g. unsigned int
vs signed int
, size_t
vs ssize_t
, etc.) in C. In C++ it would be easy with a little bit of meta-programing but in C there are far fewer options when it comes to static (aka compile-time) checking. And on this one, Google didn't help me much. So I thought I'd write something, hopefully it'll be helpful to someone searching what I was trying to find.Here is a simple trick:
#define IS_UNSIGNED_TYPE(Type) \
char ERROR_ ## Type ## _MUST_BE_UNSIGNED[((Type) -1 < 0) * -1]
Now if you call
IS_UNSIGNED_TYPE(ssize_t);
GCC will give you a nice error: size of array 'ERROR_ssize_t_MUST_BE_UNSIGNED' is negative
, whereas with size_t
it compiles fine.For those who don't understand how this works, it's pretty simple: the two hashes (
##
) are used to concatenate tokens in the macro. So for instance for the case of ssize_t
we have:char ERROR_ssize_t_MUST_BE_UNSIGNED[((ssize_t) -1 < 0) * -1]Whereas for
char ERROR_ssize_t_MUST_BE_UNSIGNED[(-2147483648 < 0) * -1]
char ERROR_ssize_t_MUST_BE_UNSIGNED[1 * -1]
char ERROR_ssize_t_MUST_BE_UNSIGNED[-1] // Invalid
size_t
we have:char ERROR_size_t_MUST_BE_UNSIGNED[((size_t) -1 < 0) * -1]Not particularly useful but ... Kind of neat, isn't it?
char ERROR_size_t_MUST_BE_UNSIGNED[(4294967295 < 0) * -1]
char ERROR_size_t_MUST_BE_UNSIGNED[0 * -1]
char ERROR_size_t_MUST_BE_UNSIGNED[0] // Valid