Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enforce strong type checking in C (type strictness for typedefs)

Is there a way to enforce explicit cast for typedefs of the same type? I've to deal with utf8 and sometimes I get confused with the indices for the character count and the byte count. So it be nice to have some typedefs:

typedef unsigned int char_idx_t; typedef unsigned int byte_idx_t; 

With the addition that you need an explicit cast between them:

char_idx_t a = 0; byte_idx_t b;  b = a; // compile warning b = (byte_idx_t) a; // ok 

I know that such a feature doesn't exist in C, but maybe you know a trick or a compiler extension (preferable gcc) that does that.


EDIT I still don't really like the Hungarian notation in general. I couldn't use it for this problem because of project coding conventions, but I used it now in another similar case, where also the types are the same and the meanings are very similar. And I have to admit: it helps. I never would go and declare every integer with a starting "i", but as in Joel's example for overlapping types, it can be life saving.

like image 698
quinmars Avatar asked Dec 17 '08 23:12

quinmars


2 Answers

For "handle" types (opaque pointers), Microsoft uses the trick of declaring structures and then typedef'ing a pointer to the structure:

#define DECLARE_HANDLE(name) struct name##__ { int unused; }; \                              typedef struct name##__ *name 

Then instead of

typedef void* FOOHANDLE; typedef void* BARHANDLE; 

They do:

DECLARE_HANDLE(FOOHANDLE); DECLARE_HANDLE(BARHANDLE); 

So now, this works:

FOOHANDLE make_foo(); BARHANDLE make_bar(); void do_bar(BARHANDLE);  FOOHANDLE foo = make_foo();  /* ok */ BARHANDLE bar = foo;         /* won't work! */ do_bar(foo);                 /* won't work! */    
like image 90
Tim Lesher Avatar answered Oct 10 '22 08:10

Tim Lesher


You could do something like:

typedef struct {     unsigned int c_idx; } char_idx;  typedef struct {     unsigned int b_idx; } byte_idx; 

Then you would see when you are using each:

char_idx a; byte_idx b;  b.b_idx = a.c_idx;   

Now it is more clear that they are different types but would still compile.

like image 38
lillq Avatar answered Oct 10 '22 08:10

lillq