C variable type assert

As you mentioned GCC, you can use a compiler extension to accomplish this in case you are not using C11:

First write a macro that emulates the C++ is_same. And then call it with the types you want to compare.

A minimal example for your particular case:


#define is_same(a, b) \
  static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")

int main()
    int fail_count = 0;    
    is_same(fail_count, unsigned int);

The compiler asserts:

<source>: In function 'main':
<source>:4:3: error: static assertion failed: "fail_count is not unsigned int"
   static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")

<source>:9:5: note: in expansion of macro 'is_same'
     is_same(fail_count, unsigned int);

See Demo

What about a low-tech solution that works even with K&R C and any compiler past and present?

Place the right comment in the right place:

 * If this type is changed, don't forget to change the macro in
 * if (fail_count < UINT32_MAX - 1) below (or file foobar.c)
uint32_t fail_count = 0;

With a proper encapsulation this should refer to exactly one place in the code. Don't tell me you increment the fail count in many places. And if you do, what about a


right next to the declaration? That's more proper and clean code anyway. No need for all the assertion magic and rocket sciencery :-)

As of C11, you can use a generic selection macro to produce a result based on the type of an expression. You can use the result in a static assertion:

#define IS_UINT32(N) _Generic((N), \
  uint32_t: 1, \
  default: 0 \

int main(void) {
  uint32_t fail_count = 0;
  _Static_assert(IS_UINT32(fail_count), "wrong type for fail_count");

You could of course use the result in a regular assert(), but _Static_assert will fail at compile time.

A better approach could be dispatching the comparison based on type, again using generic selection:

#include <limits.h>
#include <stdint.h>

#define UNDER_LIMIT(N) ((N) < _Generic((N), \
int32_t: INT32_MAX, \
uint32_t: UINT32_MAX \
) -1)

int main(void) {
  int32_t fail_count = 0;

  if (UNDER_LIMIT(fail_count)) {