What is the best way to create type-agnostic structures in C?

I am trying to write some general structures. In fact, for my purpose I need C ++ templates, but since I write in C, templates are not taken into account. I am currently considering two ways to achieve what I want.

Method 1: use a preprocessor. For example:

#define DEFINE_PAIR(T) typedef struct Pair_##T{ \ T x; \ T y; \ } Pair_##T DEFINE_PAIR(int); int main(){ Pair_int p; return 0; } 

The obvious drawback is that you must call a macro before using this type. There are probably more flaws that I hope you will point out.

Method 2: just use void pointers, for example:

 typedef struct Pair{ void* x; void* y; } Pair; 

Obviously, this approach is not type safe (I could easily pass a couple of lines to a function waiting for a couple of doubles), plus the code making the release becomes much more messy with this approach.

I would like to hear your thoughts about this. Which of the two methods is better / worse and why? Is there any other method I could use to write generic structures in C?

Thanks.

+7
source share
3 answers

If you plan on using primitive data types, then your original macro-based solution seems pretty elegant. However, when you start storing pairs of pointers on opaque data types with complex structures below them that are intended to be used by specifying pointers between functions, for example:

 complex_structure_type *object = complex_structure_type_init(); complex_structure_type_set_title(object, "Whatever"); complex_structure_type_free(object); 

then you should

 typedef complex_structure_type *complex_structure_type_ptr; 

so that

 DEFINE_PAIR(complex_structure_type_ptr); 

so you can

 Pair_complex_structure_type_ptr p; 

and then

 px = object; 

But it only works a little more, so if you feel that it works for you, go for it. You can even build your own preprocessor that goes through the code, pulls out something like Pair_whatever, and then adds DEFINE_PAIR (whatever) for the C preprocessor. Anyway, this is definitely a great idea that you presented here.

Personally, I would just use void pointers and forget about strict type security. C simply does not have the same type of security technique as other languages, and the more opportunities you give yourself to forget something, the more errors you accidentally create.

Good luck

+4
source

Noting that C ++ templates provide a language for writing code, you can simply consider creating code using some tool more powerful than a c-preprocessor.

Now, when you add another step to the creation and force you to build, it depends on another board (if you do not want to write your own generator in c ...), but this can provide the flexibility and security of the types you desire.

+2
source

It is almost the same, but it is a bit more agile:

 #define PAIR_T(TYPE) \ struct { \ TYPE x; \ TYPE y; \ } typedef PAIR_T(int) int_pair; typedef PAIR_T(const char *) string_pair; int main(void) { int_pair p = {1, 1}; string_pair sp = {"a", "b"}; } 
+1
source

All Articles