多行C宏的简单定义有什么诀窍吗?

多行C宏的简单定义有什么诀窍吗?,c,macros,c-preprocessor,generic-programming,C,Macros,C Preprocessor,Generic Programming,我试图用C语言编写一些可重用的通用类型安全代码,使用宏,类似于工作原理: 然后我将其与任何类型参数一起使用: Fifo_define(int32_t); ... Fifo(int32_t) *myFifo = Fifo_init(int32_t, 100); 然而,写这篇文章相当复杂而且容易出错,没有IDE编辑器支持(IntelliSense),所以我想知道是否有什么技巧可以让我(也许)添加一些定义,然后包含文件,而不必在每一行末尾加上\ 比如: // no idea how to do th

我试图用C语言编写一些可重用的通用类型安全代码,使用宏,类似于工作原理:

然后我将其与任何类型参数一起使用:

Fifo_define(int32_t);
...
Fifo(int32_t) *myFifo = Fifo_init(int32_t, 100);
然而,写这篇文章相当复杂而且容易出错,没有IDE编辑器支持(IntelliSense),所以我想知道是否有什么技巧可以让我(也许)添加一些定义,然后包含文件,而不必在每一行末尾加上
\

比如:

// 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
//不知道怎么做,只是检查类似的概念是否可行
#定义FIFO_类型int
#定义FIFO_名称FIFO_int
#包括
#未定义FIFO_名称
#未定义FIFO_类型

我会以某种方式得到所有正确的
struct
s和函数。问题是这些宏中有很多参数串联,因此我不确定是否可以用比第一个代码段更简单的方式来实现这一点?

在这种情况下不推荐使用,但您可以使用以下方法来实现:

但这并没有真正改善情况。它不再需要一个丑陋的
Fifo\u define
宏,因此您可以将代码分成几个部分。但宏观混乱依然存在


我会推荐一些完全不同的方法。两项建议:

  • 在运行时以经典的C方式处理类型泛型。使用回调。如果需要,使用枚举跟踪使用的类型

  • C11
    \u Generic
    允许使用各种类型的安全技巧,并可用于逐步淘汰此类混乱的宏。宏本身保持最小值,并键入不同类型的不同实现。(不管怎样,当您进行类型泛型编程时,这通常就是您最终要做的事情。)


如果使用复杂宏,请考虑使用M4而不是C预处理器。并且可以做一些事情,比如有多行而没有行连续字符

使用类似m4的代码生成器被调用

在C中使用m4可以通过将其视为预处理器来实现:


由于m4在基本级别上与C预处理器的工作方式类似,因此除了支持其自身的高级功能外,它通常会正确转换任何普通C宏。

我估计这是可能的,我见过这种宏魔术。但是,您声明(重新措辞)希望减少以“\”结尾的行数,我理解这是(值得称赞的)对可读性的渴望。我还认为会有副作用,例如需要使用“#undf”。(我有一种迷信,认为使用undef是邪恶的,即使用时容易出错。)相反,我估计宏魔法不会让事情变得更可读。
// 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
#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
% grep -v '#include' file1 file2 | m4 > outfile
% m4 file1 file2 | cc