Any trick for defining multi-line C macros more easily?
I'm trying to write some reusable universal safe code in C using macros similar to klib works:
#define Fifo_define(TYPE) \
\
typedef struct { \
TYPE *head; \
TYPE *tail; \
size_t capacity; \
} Fifo_##TYPE, *pFifo_##TYPE; \
\
inline Fifo_##TYPE * Fifo_##TYPE##_init(size_t capacity) { \
Fifo_##TYPE * fifo = calloc(1, sizeof(Fifo_##TYPE)); \
TYPE * data = calloc(capacity, sizeof(TYPE)); \
fifo->head = data; \
fifo->tail = data; \
fifo->capacity = capacity; \
}
// define macros
#define Fifo(TYPE) Fifo_##TYPE
#define Fifo_init(TYPE, capacity) Fifo_##TYPE_init(capacity)
And then I just use it with any type parameter:
Fifo_define(int32_t);
...
Fifo(int32_t) *myFifo = Fifo_init(int32_t, 100);
However, writing this is quite complex and error prone with no IDE editor support (IntelliSense), so I wondered if there were any tricks that could allow me to (perhaps) add multiple definitions and then include the file without to complete each line \
?
Something like:
// no idea how to do this, just checking if similar concept is possible
#define FIFO_TYPE int
#define FIFO_NAME Fifo_int
#include <generic-fifo.h>
#undef FIFO_NAME
#undef FIFO_TYPE
And I would somehow get all the correct ones struct
and functions. The problem is that there is a lot of parameter concatenation in these macros, so I'm not sure if this can be done easier than the first snippet?
source to share
Not recommended in this case, but you can do something like what you want to achieve, X-macro :
#define SUPPORTED_TYPES \
X(int) \
X(double) \
X(char)
#define X(TYPE) \
typedef struct { \
TYPE *head; \
TYPE *tail; \
size_t capacity; \
} Fifo_##TYPE, *pFifo_##TYPE;
SUPPORTED_TYPES
#undef X
#define X(TYPE) \
inline Fifo_##TYPE * Fifo_##TYPE##_init(size_t capacity) \
{ \
Fifo_##TYPE * fifo = calloc(1, sizeof(Fifo_##TYPE)); \
TYPE * data = calloc(capacity, sizeof(TYPE)); \
fifo->head = data; \
fifo->tail = data; \
fifo->capacity = capacity; \
}
SUPPORTED_TYPES
#undef X
But that didn't improve the situation much. It got rid of the need for one, ugly macro Fifo_define
so that you can split your code into multiple sections. But the macro mess remains.
I would recommend a completely different approach. Two suggestions:
-
Process common things in classic C mode at runtime. Use callbacks. Track the used enumerated type as needed.
-
C11
_Generic
allows all sorts of type safety tricks and can be used to phase out such dirty macros. An example that implements "functors" . The macro itself is kept minimal, and different implementations for different types are printed. (This is usually what you end up doing when you do sample programming.)
source to share
If you are using complex macros, consider using m4 instead of a C pre-processor. M4 is similar to a C pre-processor, but much more powerful and can do something like multiple lines without a line-continuation character.
Using code generators like m4 is called metaprogramming .
Using m4 in C can be done by treating it as a pre-processor like this :
% grep -v '#include' file1 file2 | m4 > outfile
% m4 file1 file2 | cc
Since m4 works in a similar way to a C pre-processor at a basic level, it will usually convert any regular C macros in addition to supporting its own extended functionality.
source to share