How do I write a generic display function in C to display void pointers of all data types?
You cannot do that reliably, unless your display function is given some way of display values. And mostly because C types are not known at run-time (they are erased): the same sequence of bits could be a char*
string or some array of double
-s (perhaps even inside some union
). Consider perhaps learning Ocaml which has a stricter and somehow safer type system (and retain some type information at runtime).
BTW, you could store inside your "generic" stack_T
both the sizeof
and the alignof
pointed values. Then you could have, with some coding pain, one less indirection by using flexible array members. This might be more efficient (in some cases) because of your CPU cache.
A possibility might be to pass a callback function to your display function. You could for example pass as argument a function pointer displaying the pointed values.
Declare first (for readability) a signature
typedef void element_display_sigt (void*displayed_data);
Then declare your displaying function to take such a function pointer
void display_stack(stack_T *stack, element_display_sigt*dispfun);
Actually, what you dream of are closures. They don't exist in C17. Check by reading n2176 (a draft C standard) and Modern C
In practice, your element_display_sigt
would often take an extra argument, for example a FILE*
to write to. And your display_stack
would also have that extra argument.
FWIW, closures exist (and also anonymous functions) in modern C++, in Scheme, in Common Lisp, in Ocaml, in Haskell, in Lua. I heard that future C standards might add anonymous functions to C.
You could consider embedding an interpreter like Lua or GNU Guile (a nice Scheme implementation) in your application coded in C.
You might be interested in reading the Dragon book, about λ-calculus, and about garbage collection.
If you code for Linux, be aware of dlopen(3) and dlsym(3) : in some cases, it might be worthwhile to generate the C code of some plugin at runtime, then compile that code into a shared object library, then use that dlopen
-ed plugin or shared object at runtime. My manydl.c example shows that this can be done thousands of times. Another possibility might be to use machine code generation libraries like GNU lightning or libgccjit.
Be also aware that GNU libc specifically still has (at end of 2020) a way of customizing printf
Another approach is to generate some (printing) C code at build time, with tools inspired from SWIG. You could either write your own GCC plugin generating printing code or, using GNU bison, write your own C code generator.