Type-safety in C

The problem is that C doesn’t treat your two typedefs as distinctive types, because they are both type unsigned.

There are various tricks to dodge this. One thing would be to change your types to enums. Good compilers will enforce stronger typing warnings on implicit conversions to/from a certain enum type to any other type.

Even if you don’t have a good compiler, with enums you could do this:

typedef enum { FOO_CENT  } cent_t;
typedef enum { FOO_DOLLAR} dollar_t;

#define DOLLAR_2_CENT(dollar)       ((cent_t)(100*(dollar)))

void calc(cent_t amount) {
    // expecting 'amount' to semantically represents cents...
}

#define type_safe_calc(amount) _Generic(amount, cent_t: calc(amount))

int main(int argc, char* argv[]) {
    dollar_t amount = 50;
    type_safe_calc(DOLLAR_2_CENT(amount));  // ok
    type_safe_calc(amount);         // raise warning

    return 0;
}

A more conventional/traditional trick is to use a generic struct wrapper, where you use a “ticket” enum to mark the type. Example:

typedef struct
{
  type_t type;
  void*  data;
} wrapper_t;

...

cent_t my_2_cents;
wrapper_t wrapper = {CENT_T, &my_2_cents};

...

switch(wrapper.type)
{
  case CENT_T: calc(wrapper.data)
  ...
}

The advantage is that it works with any C version. Disadvantage is code and memory overhead, and that it only allows run-time checks.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)